React 18: Nové funkce v reálných projektech. To dobré a problémy

V tomto článku se budeme zabývat použitím React 18 ve skutečných produkčních projektech a jak to ovlivňuje projekty používající "dobré" a staré Create React App (CRA). Budeme diskutovat o funkcích, které přicházejí s aktualizací, a o některých potřebných opravách.

20 Feb 2023
9 min read

React 18.png

Datum vydání React 18: Panoramatický pohled

React 18 byl vydán v březnu 2022. Tato hlavní verze populární JavaScriptové knihovny přináší řadu vzrušujících nových funkcí a vylepšení pro ekosystém Reactu. React 18 byl komunitou vývojářů netrpělivě očekáván a od té doby získal pozitivní recenze díky svým pokrokům v renderování dat a plynulých přechodech mezi stránkami a komponentami.

Porozumění dopadu automatického sdružování v React 18 na správu stavu a výkon

Jednou z hlavních změn v React 18 je automatické sdružování, které zlepšuje spotřebu paměti a výkon tím, že sdružuje aktualizace stavu do jednoho překreslení. Tato funkce však někdy vyžaduje přehodnocení správy stavu v aplikaci.

Bylo napsáno mnoho o tom, jak sdružování funguje, například tento článek na toto téma.

Když jsem aktualizoval React v mých projektech, které používají CRA, nenarazil jsem na žádné významné problémy, až na jeden případ. Měl jsem dashboard s několika kartami, každá obsahovala tlačítko a vstupy pro provádění akcí. Dashboard měl však také odpočítávací časovač, který způsoboval problémy se stavem a vykreslováním tlačítek pro akce. Trvalo mi několik dní, než jsem problém pochopil, což mě nakonec vedlo k tomu, že jsem snížil verzi Reactu.

Po vyšetření jsem zjistil, že problém byl způsoben knihovnou Formik, která nebyla již nějakou dobu aktualizována ani udržována. Formik způsoboval konflikty se změnami stavu vyvolanými časovačem. Řešením bylo opustit Formik a nahradit jej knihovnou jako React Hook Form.

dd8d8605-0731-49e8-a790-b651c099daca.png

Renderování klienta v React 17

Nyní pojďme hovořit o změnách ve způsobu renderování React komponent od verze 17 do 18, zejména o výhodách a nevýhodách každého přístupu, a uvedeme příklady produkčních scénářů, se kterými jsem se setkal.

React 17 pracuje s renderováním na straně klienta jako s výchozí a nejčastěji používanou metodou. To znamená, že komponenty jsou renderovány v prohlížeči uživatele pomocí virtuálního DOM, aby se s datovými změnami aktualizovalo uživatelské rozhraní. Když uživatel navštíví webovou stránku nebo webovou aplikaci postavenou na Reactu 17, server pošle počáteční HTML spolu s JavaScriptovým kódem pro React komponenty. Prohlížeč pak tento kód vykoná a vyrenderuje komponenty, což umožňuje uživateli interagovat s uživatelským rozhraním.

a7bf58b3-b6f8-40b1-ab99-6dd1ce8506fb.png

One of the main advantages of client-side rendering is the ability to quickly update and provide interactive experiences. The components can easily be re-rendered on the client without requiring a full page refresh. It also allows for the use of client-side state and APIs, which are not available on the server. However, it can also lead to slower initial load times as the browser must first download and execute the JavaScript before rendering the components, which may be an issue for users on slow connections.

Rendering from the server (SSR) in React 18

React 18 introduces the option of server-side rendering (SSR), where the initial rendering of the components is done on the server instead of the client. When a user visits a website or web application built with React 18 and server-side rendering, the server will generate the HTML for the initial render of the components and send it to the client. The client then "hydrates" the pre-rendered HTML with the JavaScript code, matching the references.

Toto vede ke zlepšeným počátečním načítacím časům, protože server může klientovi odeslat plně vykreslené HTML, které může být okamžitě zobrazeno. To také umožňuje použití nových API, jako jsou Suspense a useTransition. Nicméně to může být také složitější na implementaci a může způsobovat problémy s komponentami, které spoléhají na API, protože počáteční vykreslení na serveru nemá přístup k těmto API.

Výzvy a řešení při používání server-side renderingu React 18 s Suspense pro načítání dat

Používání server-side renderingu (SSR) React 18 s Suspense může představovat výzvy, pokud jde o načítání dat. Protože Suspense spoléhá na stavy na straně klienta a API, není na serveru podporováno, což vede k neúplnému serverem vykreslenému HTML pro komponenty, které používají Suspense pro načítání dat. Pro řešení tohoto problému je nutné použít alternativní přístup k načítání dat. Tým React uznal, že SSR s načítáním dat nebylo navrženo pro běžné použití v projektech Create React App a doporučuje použití frameworku jako NextJS nebo Remix, který tuto funkci implementuje přímo z krabice. Nicméně v pracovním projektu nemusí být proveditelné celou strukturu aplikace přepracovat.

Příklad z produkční aplikace

V jednom z mých nedávných projektů jsem narazil na výzvu při upgradu z React 17 na React 18. Problém nastal, když stránka v aplikaci načítala data z backendu a zároveň zobrazovala načítací spinner. Po upgradu byla uživatelům zobrazena výchozí HTML stránka před dokončením načítání dat, což způsobilo obnovení celé stránky a správné informace byly zobrazeny až následně.

Pro vyřešení tohoto problému jsem musel najít řešení, které by fungovalo v rámci omezení server-side renderingu (SSR) a routingu celé aplikace. Mé řešení spočívalo ve vytvoření podmínky pro vykreslení komponenty stránky. Nastavil jsem komponentu tak, aby se vykreslovala pouze tehdy, když byla data přítomna, a zobrazil načítací spinner, pokud data ještě nebyla dostupná. Tímto způsobem během počátečního vykreslení HTML podmínka nebyla splněna a stav byl false, což způsobilo zobrazení načítacího spinneru. Jakmile byla data načtena, komponenta se mohla vykreslit se všemi potřebnými informacemi a správným hydratovaným HTML.

Zlepšení pomalých připojení a aplikací s vysokým objemem dat pomocí Suspense:

Suspense je výkonný nástroj, který může v určitých situacích vylepšit uživatelskou zkušenost.

Za prvé, může být zvláště prospěšný pro uživatele s pomalým internetovým připojením nebo zařízeními. Suspense umožňuje zobrazit záložní komponentu, jako je stránka nebo ikona načítání, zatímco se JavaScript načítá, místo aby uživatel viděl prázdnou stránku.

Za druhé, Suspense lze také využít k optimalizaci částí aplikace s velkým množstvím dat. Přizpůsobením Suspense lze aplikovat pouze na specifické komponenty, což umožňuje zobrazit téměř celou stránku uživateli, kromě načítajících se částí, jejichž zobrazení bude odloženo.

Navigace ve Fetchingu Dat v Reactu: Nadcházející Hook "use"

Očekává se, že budoucí verze Reactu řeší výzvy, které aktuálně přináší využití Suspense pro server-side rendering (SSR) a fetching dat. Jedním z řešení, které se v současné době diskutuje, je zavedení nového hooku nazvaného "use". Tento hook umožní vývojářům přistupovat k asynchronním zdrojům dat s využitím Suspense prostřednictvím stabilního API. Více se o tom můžete dočíst na tomto odkazu. I když toto řešení zatím není k dispozici, tým Reactu stále pracuje na implementaci funkce cache pro tento hook. Mezitím mohou ti, kdo využívají Create React App (CRA), potřebovat najít obcházení a hacky, jak řešit fetching dat ve svých aplikacích.

Zlepšení Uživatelské Zkušenosti s Hookem "useTransition" v Reactu 18: Implementace Plynulých Přechodů ve Vaší Aplikaci

Pro vytvoření plynulého a příjemného zážitku pro uživatele je důležité věnovat pozornost vizuálním efektům při přechodu mezi stránkami nebo komponentami v aplikaci. React 18 představil nové API nazvané "useTransition", které umožňuje vývojářům snadno implementovat přechody. Hook "useTransition" vrací dvojici obsahující dva objekty: "isPending", který indikuje, zda je přechod dokončen, a "startTransition", metodu, kterou lze zavolat pro zahájení přechodu.

Tento hook může být zvláště užitečný, když se používá ve spojení s Suspense, protože může poskytnout plynulý zážitek pro uživatele, zatímco se načítají nové komponenty nebo stránky. Například, pokud je metoda použita pro obsluhu kliknutí pro změnu záložky na stránce, přechod může být zahájen tam a boolean "isPending" může být použit jako stav načítání pro komponentu.

Prozkoumání rozdílů mezi ručním načítáním v Reactu 17 a Suspense a useTransition v Reactu 18

Poskytuji vám dvě ukázkové sandboxy, abyste mohli porovnat metody načítání stránek a stavů v Reactu. První sandbox používá tradiční metody v Reactu 17, zatímco druhý využívá nový Suspense a hook useTransition v Reactu 18.

První sandbox demonstruje ruční načítání s Reactem 17: react-17-loading-content-switch-tabs - CodeSandbox

Druhý sandbox ukazuje, jak lze v Reactu 18 použít Suspense a useTransition: react-18-loading-content-suspense-useTransition - CodeSandbox

Oba sandboxy simuluji pomalý API požadavek pomocí setTimeout.

Sandbox React 17 demonstruje ruční načítání a použití stavu načítání, což může vést ke zpožděním pro uživatele při přepínání mezi záložkami. Naproti tomu sandbox React 18 využívá hook useTransition, který umožňuje plynulejší uživatelský zážitek během načítání nového obsahu. Proces načítání je indikován postupně se zabarvující horní lištou, což je méně rušivé pro uživatele.

Je důležité poznamenat, že i když může být Suspense užitečné pro načítání komponent, s fetchingem dat ve vanilkové React aplikaci dobře nefunguje. Proto sandbox React 18 zahrnuje také normální načítač pro fetching dat, stejně jako globální načítač, který využívá setTimeout k aktivaci Suspense během načítání komponenty, zobrazující zabarvenou horní lištu.

Porozumění novým přístupům k vykreslování dat: fetch-as-render, render-then-fetch

Podívejme se na nové přístupy k vykreslování dat v Reactu 18 s uvedením server-side renderingu a Suspense. Nyní jsou k dispozici dva nové přístupy, "fetch-as-render" a "render-then-fetch", které se liší od tradičního přístupu "fetch-then-render", který byl používán v Reactu 17.

Obě tyto nové metody umožňují vykreslování probíhat současně s načítáním dat, nikoli sekvenčně, jak tomu bylo dříve. To umožňuje lepší uživatelskou zkušenost, protože data se načítají na pozadí, zatímco uživatel interaguje se stránkou.

Pro ilustraci rozdílu mezi těmito přístupy si představte následující obrázek:

V tradičním přístupu "fetch-then-render" probíhá načítání dat sekvenčně, jeden API volání po druhém. S přístupy "fetch-as-render" a "render-then-fetch" lze provádět několik API volání současně, zatímco HTML může být již vykresleno, což vede k efektivnějšímu celkovému procesu.

Navíc je také možné přizpůsobit načítání každé komponenty použitím různých Suspense v SuspenseListu:

Překonávání běžných problémů: Řešení běžných problémů

Migrace na React 18 může být náročná, zejména pokud jde o správnou implementaci nových funkcí. Je nezbytné pochopit, jak aktualizace React 18 ovlivní vaši aplikaci, a důkladně ji naplánovat a otestovat, abyste se vyhnuli problémům. Zde jsou některé běžné problémy a jejich možná řešení:

Automatické dávkování:

-** Problém:** V některých případech může automatické dávkování kombinovat aktualizace stavu, což vede ke konfliktům s knihovnami třetích stran nebo externími úložišti.

  • Řešení: Uložení stavu jinde nebo přepnutí z useState na useRef, aby se zabránilo opětovnému vykreslení komponenty.

Vícenásobné namontování:

  • Problém: V režimu vývoje se zapnutým přísným režimem se mohou komponenty vykreslovat dvakrát kvůli useEffect bez závislostí. Je to důsledek nového cyklu striktního režimu: mount → render → unmount → mount → render.
  • Řešení: Dočasně zabalte kód useEffect do podmínky useRef, aby se kód spustil pouze jednou. Ve výrobě se komponenta připojí a vykreslí jednou, jak se očekává.

Suspense nefunguje při načítání dat:

  • Problém: Vývojáři React doporučují pro bezproblémovou funkci Suspense používat frameworky jako NextJS nebo knihovny jako react-query místo Create React App.
  • Řešení: V CRA lze řešení najít v přesouvání stavů, přidání loaderů pro fetching dat nebo použití useTransition. Řešením může být také připravovaný háček "use".

React je s každou další verzí stále složitější, což vede ke vzniku záludných chyb. Například:

  • Knihovny jako Formik mohou způsobovat problémy s React 18 a řešením je přepnutí knihovny.
  • U Reactu je zásadní optimalizovat každou komponentu pomocí háčků, jako jsou memo, useMemo a useCallback, aby se předešlo problémům. Ostatní frameworky, jako je Vue a SvelteKit, mají tyto funkce zabudované.

Závěr

Někdy vás tyto zlomové změny donutí kompletně změnit strukturu projektu kvůli jedné nefunkční věci.

Narůstající vrstvy složitosti v Reactu jsou zajímavé, ale zároveň únavné. K chybám dochází a je těžké pochopit proč. Zvlášť pro někoho, kdo se to začíná učit až teď.

Závěrem lze říci, že React 18 přináší několik nových funkcí, které mohou zlepšit uživatelský zážitek z vašich aplikací. Je však důležité uvědomit si potenciální problémy, které mohou vzniknout při nesprávné implementaci React 18, jako je automatické dávkování a vícenásobné montování, a zvážit možná řešení těchto problémů.