W kwietniu zespół odpowiedzialny za rozwój Reacta zapowiedział nowe funkcjonalności, które najprawdopodobniej pojawią się w nadchodzącej 19 wersji tej biblioteki.
Od tego czasu minęło już kilka miesięcy i mimo że oficjalnej daty premiery jeszcze nie ma, to można się spodziewać, że nastąpi to niedługo. Najwyższy czas przygotować się na to, co nas czeka i zapoznać ze wszystkimi nowościami i zmianami.
Zmiany
Obecne dotąd funkcjonalności nie uległy zbyt wielkim zmianom. Można tu raczej mówić o kosmetycznych poprawkach niż o rewolucji. W związku z tym migracja do najnowszej wersji nie powinna zaburzyć funkcjonowania istniejących stron i aplikacji, a biblioteka nadal zachowuje wsteczną kompatybilność.
Nie oznacza to jednak, że nie zmieniło się nic, dlatego zanim przejdziemy do nowości, omówmy różnice w funkcjonalnościach z których korzystaliśmy do tej pory.
Ref
Mimo że zmiana jest drobna, to muszę przyznać, że długo na nią czekałem. Od wersji 19 ref
będzie można przekazać w ten sam sposób, jak pozostałe propsy. Nie trzeba będzie wykorzystywać funkcji forwardRef
.
Druga zmiana dotycząca refa to możliwość przekazania funkcji “sprzątającej”. Zapis wygląda identycznie jak w przypadku useEffect
. Pierwsza część funkcji zostanie wykonana w momencie zamontowania elementu w DOM, natomiast zwrócona wartość zostanie wykonana po jego usunięciu z drzewa DOM.
Kod wykonywany wewnątrz tej funkcji zależy tylko od nas (podobnie jak w przypadku useEffect
). Nic nie stoi zatem na przeszkodzie, żeby stworzyć mapę z referencjami do poszczególnych elementów, a w momencie usunięcia elementu z DOM, usunąć go także z mapy.
Do tej pory React sam wykonywał funkcję sprzątającą i przekazywał do niej wartość null
. Jeżeli zdecydujemy się sami ją stworzyć, to to zachowanie zostanie nadpisane. Dodatkowo, twórcy Reacta zapowiadają, że w kolejnych wersjach zostanie ono oznaczone jako deprecated i zostanie zachowane tylko w celu kompatybilności wstecznej.
Context
Od wersji 19 nie będziemy musieli odwoływać się do właściwości Provider
w obiekcie context. Zamiast tego możemy go użyć bezpośrednio, jako komponentu:
Twórcy obiecują także dostarczenie codemoda (funkcji operującej na naszym kodzie bez konieczności wprowadzania manualnych zmian), który zamieni starą składnię na nową.
Metadata
Meta tagi, takie jak title lub link, od zawsze były problematyczne w aplikacjach Reacta. Oczywiście w przypadku statycznych wartości, które nie zmieniają się wraz ze zmianą URLa nie był to wielki problem, jednak dynamiczne wartości są znacznie częściej stosowane. W końcu każda strona powinna mieć swój własny tytuł i tagi OG.
W React 19 tagi <link>
, <meta>
oraz <title>
będą automatycznie przenoszone do wnętrza tagu <head>
w dokumencie HTML. Twórcy gwarantują również ich poprawne działanie w przypadku stosowania SSR, RSC oraz aplikacji renderowanych w całości po stronie klienta.
Co prawda w oficjalnej dokumentacji Reacta znajdziemy wzmiankę o tym, że celem tej funkcjonalności nie jest zastąpienie takich bibliotek jak react-helmet, a jedynie ułatwienie życia ich twórcom, jednak ciężko się oprzeć wrażeniu, że wraz z wprowadzeniem tej zmiany mogą się one okazać zbędne.
Web Components
O komponentach sieciowych (ang. Web Components lub WC) wspominałem już jakiś czas temu na blogu. Jeżeli ten temat jest dla Ciebie nowością, to koniecznie przeczytaj najpierw artykuł na ten temat.
Do tej pory integracja WC z Reactem nie była oczywista i wymagała od programisty konwertowania komponentów sieciowych na komponenty Reacta lub pisania dodatkowego kodu w celu poprawnego działania (React traktuje nierozpoznane właściwości jako atrybuty, a nie propsy). Od wersji 19 ten problem powinien zniknąć, a używanie komponentów sieciowych w aplikacji Reacta nie będzie wymagać dodatkowego kodu lub zewnętrznych bibliotek.
useDeferredValue
useDeferredValue istnieje w React już od jakiegoś czasu i daje nam możliwość przekazania wartości, która następnia zostanie “opóźniona”. Jeżeli na jej podstawie wyświetlany jest UI, to on również zostanie zmieniony w późniejszym etapie. Głównym jego zastosowaniem jest poprawa wydajności naszej aplikacji.
W React 19 otrzymujemy możliwość przekazania do środka wartości początkowej, która zostanie użyta podczas pierwszego renderowania komponentu.
Nowości
Nowości jest wiele, a do tego są naprawdę znaczące. Komponenty serwerowe zmieniły niemal całkowicie sposób podejścia do tworzenia aplikacji z wykorzystaniem NextJS, a w połączeniu z akcjami stanowią naprawdę potężne narzędzie. Dodatkowo otrzymaliśmy kilka nowych hooków, głównie do obsługi wspomnianych wcześniej akcji.
Szczegółowe omówienie wszystkich punktów z powyższej listy jest niemal niemożliwe w jednym artykule dlatego skupię się tu na ogólnym działaniu, a poszczególnym funkcjonalnościom poświęcę osobne artykuły, w których szczegółowo je opiszę (w miarę dodawania kolejnych publikacji będę również edytować ten artykuł w celu dodania do niego odpowiednich linków).
Komponenty Serwerowe
O komponentach serwerowych mówi się już od jakiegoś czasu, a NextJS daje możliwość skorzystania z nich już dziś. Jednak dopiero w kolejnej wersji Reacta zostaną one oznaczone jako “stabilne”, co w praktyce oznacza, że będzie je można bez obaw wykorzystywać w aplikacjach produkcyjnych, a do istniejącego, publicznego API nie zostaną wprowadzone żadne znaczące zmiany (a przynajmniej dopóki nie ukaże się kolejna wersja).
A teraz już do rzeczy. Komponenty serwerowe, jak sama nazwa wskazuje, zostają uruchomione wyłącznie po stronie serwera, a do klienta (np. przeglądarki) trafia jedynie efekt tego wywołania. Oznacza to, że wewnątrz komponentu Reacta możemy bezpośrednio wysyłać zapytania do bazy danych i wszelkie inne czynności, za które odpowiada backend (ostatecznie ten kod będzie wykonany po stronie backendu).
Przykładowy komponent serwerowy może wyglądać następująco:
Oczywiście ten krótki opis nie wyczerpuje tematu. Jest on na tyle rozbudowany, że postanowiłem poświęcić mu osobny artykuł.
Funkcje serwerowe
Poprzednia nazwa tej funkcjonalności to akcje serwerowe (ang. Server Actions). Twórcy Reacta zdecydowali się na zmianę, ponieważ programiści zaczęli wykorzystywać je nie tylko do obsługi formularzy i prostych serwerowych akcji, ale również do tworzenia zapytań do baz danych i wielu, wielu innych (prawdopodobnie nieprzewidzianych przez Reacta) rzeczy.
Więc czym właściwie są funkcje serwerowe? Najprościej rzecz ujmując, są to funkcje, które mogą zostać wywołane przez komponenty (zarówno klienta, jak i serwrowe) i wykonane na serwerze. Jeżeli chwilę się nad tym zastanowimy, to okaże się, że jest to opis endpointa w API. Różnica polega jednak na tym, że zamiast tworzyć ten endpoint sami, możemy po prostu utworzyć asynchroniczną funkcję i wykorzystać dyrektywę “use server”
.
Jeżeli planujemy wykorzystać utworzoną w ten sposób funkcję w komponencie klienta, to musi ona zostać utworzona w osobnym pliku. W innym przypadku byłaby widoczna w kodzie, który trafia do przeglądarki.
Ostatni krok to wykorzystanie utworzonej funkcji:
Dzięki funkcjom i komponentom serwerowym, React staje się czymś, co zazwyczaj określa się mianem fullstack framework, a granica pomiędzy klientem i serwerem zostaje mocno zatarta. Oczywiście funkcje serwerowe nie zastąpią “prawdziwego” backendu i nie jest to ich celem. Mają one jedynie ułatwić aplikacji klienta pobieranie i modyfikowanie danych potrzebnych do jej działania. Nadal jednak potrzebujemy serwisów, które obsłużą całą logikę po stronie serwera.
Use
Hook use
to nowość, na którą czekało wielu programistów. Z jego pomocą możemy w prosty sposób odczytać wartość z contextu lub Promise
i w przeciwieństwie do innych hooków Reacta, możemy go używać w pętlach, warunkach, itp..
Do tej pory standardowym schematem było utworzenie stanu za pomocą useState
, a następnie użycie useEffect
w celu pobrania danych z API lub odczytania Promise
. Poniższy kod z pewnością nie jest Ci obcy:
Ten sam kod możemy znacznie uprościć, wykorzystując use
:
use
współpracuje także z Error oraz Suspense Boundary. Jeżeli Promise
zostanie odrzucony (rejected), błąd zostanie przechwycony przez najbliższą granicę błędu. Natomiast do czasu jego rozwiązania (pending) wyświetlony zostanie komponent zastępczy przekazany do najbliższego komponentu Suspense.
Drugie zastosowanie use
, to odczytywanie danych z contextu. W tym przypadku składnia jest identyczna, a jedyna zmiana, to przekazanie contextu zamiast Promise
:
Twórcy Reacta sugerują, że powinniśmy stosować use
zamiast useContext
z uwagi na krótszy zapis i większą elastyczność.
Podsumowanie
W przypadku poprzednich wersji Reacta mieliśmy do czynienia raczej z ewolucją niż rewolucją. To podejścia zupełnie zmienia się w najnowszej, 19stej wersji. Komponenty i funkcje serwerowe są z natury przeznaczone dla twórców frameworków opartych na React niż dla programistów frontend, a samodzielna implementacja wsparcia dla nich wymaga stworzenia skomplikowanego backendu (a następnia utrzymywania go) oraz zastosowania i skonfigurowania bundlera (np. Webpack) wspierającego te rozwiązania.
React daje jasny sygnał, że zaczyna być biblioteką nie dla końcowego odbiorcy - programisty frontend, a raczej dla twórców oprogramowania open-source, którzy opierają na nim swoje własne biblioteki. Oczywiście nie da się nie zauważyć, że aktualnie w tej kategorii przoduje NextJS, który jako jedyny wspiera wszystkie wymienione nowości i zmiany. Nie można również nie wspomnieć o kontrowersjach, jakie wywołuje wśród programistów, najnowsza aktualizacja Reacta. Wiele osób krytykuje tak drastyczną zmianę podejścia i wypowiada się sceptycznie na jej temat. Warto jednak pamiętać, że nie musimy z dnia na dzień przepisać wszystkich aplikacji oparty o React lub NextJS, a “stare” podejście, prawdopodobnie nadal będzie wspierane przez długi czas.