React 19.2 wyjaśnione: Activity, useEffectEvent i renderowanie statyczne
Dowiedz się, w jaki sposób nowy komponent Activity, hook useEffectEvent oraz częściowe renderowanie statyczne w React 19.2 eliminują ukryte koszty wydajności w nowoczesnych interfejsach użytkownika.
React 19.2 w cichy sposób potwierdza to, co deweloperzy przypuszczali od lat: niszczenie i odbudowywanie komponentów przy każdym cyklu ukrywania i pokazywania nigdy tak naprawdę nie było tanie.
Załóżmy typowy scenariusz: użytkownik przechodzi między dwoma kartami w twojej aplikacji. Lista ponownie ładuje swoje dane. Formularz zostaje wyczyszczony. Pozycja przewijania jest resetowana na górę. Dzieje się to przy każdym takim przełączeniu, ponieważ React cały czas niszczył i odbudowywał interfejs, którego tak naprawdę nie musiał usuwać.
To nie jest coś, co sam zepsułeś w swoim kodzie. To po prostu sposób działania Reacta od jego najwcześniejszych wersji. Dzięki React 19.2 framework w końcu stawia czoła temu problemowi bezpośrednio.
Problem, o którym nikt nie mówi
Większość porad dotyczących wydajności krąży wokół tych samych problemów: zbyt częste uruchamianie efektów, zbędne żądania sieciowe lub zapomnienie o umieszczeniu wartości w useMemo. Te kwestie są uzasadnione. Istnieje jednak jeszcze jeden, rzadko omawiany koszt: nakład pracy związany z wielokrotnym montowaniem i demontowaniem komponentów.
Pomyśl o panelu sterowania z kartami, strukturze nawigacji w stylu mobilnym lub modalu, który jest otwierany i zamykany wielokrotnie w trakcie jednej sesji. Za każdym razem, gdy coś ukrywasz za pomocą wyrażenia warunkowego takiego jak {isVisible && <Component />}, React nie wstrzymuje tej części interfejsu — po prostu ją całkowicie usuwa. Stan jest wymazywany, efekty są rozbierane i uruchamiane od nowa. Gdy treść ponownie się pojawia, DOM musi zostać odbudowany, jakby nigdy nie istniał.
Dla małych, prostych komponentów ten koszt jest niewidoczny. Jednak w przypadku paneli kontrolnych obciążonych dużą ilością danych, wgranych odtwarzaczy wideo lub czegokolwiek, co obejmuje ciężki widget od third party, to ciągłe niszczenie i odbudowywanie staje się poważnym obciążeniem dla wydajności.
Rozwiązanie właśnie tego problemu było głównym celem React 19.2, obok dwóch innych ulepszeń, o które prosili deweloperzy.
1. Komponent — Zatrzymaj się przed niszczeniem
To najważniejsza nowość w tym wydaniu i stanowi prawdziwie nowy kierunek w sposobie, w jaki React radzi sobie z ukrytym interfejsem użytkownika.
Teraz możesz oznaczyć część swojej interfejsu jako widoczną lub ukrytą, bez konieczności całkowitego jej odłączenia, korzystając z nowego komponentu Activity. Gdy treść jest ukryta, zachowuje swój obecny stan, pomija wykonywanie swoich efektów, a jej proces renderowania jest przeniesiony na niższy priorytet, dzięki czemu nigdy nie konkuruje z tym, co faktycznie jest widoczne na ekranie.
import { unstable_Activity as Activity } from 'react';
function Dashboard({ activeTab }) {
return (
<>
<Activity mode={activeTab === 'analytics' ? 'visible' : 'hidden'}>
<AnalyticsPanel />
</Activity>
<Activity mode={activeTab === 'settings' ? 'visible' : 'hidden'}>
<SettingsPanel />
</Activity>
</>
);
}
Dzięki temu wzorcowi AnalyticsPanel ukryty w karcie na tle nie odświeża swoich danych ani nie traci pozycji przewijania po powrocie – cały czas pozostawał bezczynny. Funkcja Activity w React 19.2 działa w dwóch trybach: w trybie hidden dzieci są widocznie ukryte, ale nie usuwane z drzewa – ich efekty pozostają zamontowane, natomiast wszystkie planowane aktualizacje są odkładane do chwili, gdy naprawdę nie będzie nic pilniejszego do przetworzenia; w trybie visible dzieci są renderowane normalnie, bez żadnych zakłóceń w procesie aktualizacji. Przydatnym efektem ubocznym tego rozwiązania jest możliwość wstępnego renderowania kart, których użytkownik jeszcze nawet nie kliknął.
Przykłady zastosowań w praktyce:
- Formularze, w których użytkownicy wielokrotnie przemieszczają się tam i z powrotem pomiędzy poszczególnymi krokami
2. useEffectEvent — Stabilna logika zdarzeń w efektach
Jeśli kiedykolwiek umieściłeś funkcję w tablicy zależności useEffect wyłącznie po to, by uciszyć narzędzie do sprawdzania kodu, tylko po to, by zobaczyć, jak twój efekt uruchamia się znacznie częściej, niż powinien, to ten hook rozwiązuje dokładnie ten problem.
function ChatRoom({ roomId, theme }) {
const onConnected = useEffectEvent(() => {
showNotification(`Connected to ${roomId}`, theme);
});
useEffect(() => {
const connection = createConnection(roomId);
connection.on('connected', () => onConnected());
connection.connect();
return () => connection.disconnect();
}, [roomId]); // theme no longer needs to be here
}
Wewnątrz onConnected zawsze odczytuje się najnowszą wartość theme, jednak samo aktualizowanie theme nie powoduje ponownego połączenia z salą czatową. Jest to w istocie oficjalna wersja rozwiązania awaryjnego, które deweloperzy od lat tworzyli ręcznie przy użyciu useRef — React teraz nadaje mu nazwę oraz pełne wsparcie.
3. Częściowe renderowanie statyczne — strony o szybkości statycznej z danymi w czasie rzeczywistym
Jest to funkcja opcjonalna przeznaczona dla zespołów tworzących aplikacje renderowane na serwerze. Niezależnie od tego, czy używasz Next.js, Remix, czy pracujesz bezpośrednio z RSC, React 19.2 umożliwia wcześniejsze renderowanie statycznej struktury strony, a następnie dodawanie elementów dynamicznych w momencie, gdy są gotowe.
Większa część strony jest renderowana od razu jako niezmieniająca się struktura. Wszystko, co zależy od połączenia sieciowego, jest uzupełniane później i łączone poprzez strumieniowanie, gdy tylko przyjdą dane. Dzięki temu odwiedzający widzą natychmiast pasek nawigacji oraz sekcję główną, podczas gdy elementy spersonalizowane pojawiają się chwilę później, bez konieczności pokazywania spinera na całej stronie.
Główny wniosek
Podstawowym przesłaniem React 19.2 jest to, że nie chodzi o radykalną przepracowę frameworka – to React koryguje założenia wbudowane w jego model około dekady temu. Ukrywanie czegoś nie powinno zmuszać do jego usunięcia. Tworzenie efektów nie powinno oznaczać wyboru między przestarzałymi wartościami a niepotrzebnym ponownym wykonywaniem operacji. A szybkość pierwszego narysowania strony nie powinna być ograniczana przez naj wolniejszą odpowiedź API.
Jeśli twoja aplikacja wykazuje powolne działanie w sposób, którego useMemo i React.memo nigdy w pełni nie rozwiązują, to ta aktualizacja prawdopodobnie jest skierowana właśnie na ten problem. Spróbuj w tym tygodniu zastosować jeden z tych wzorców do widoku z kartami w swoim projekcie — zmiana jest niewielka, ale wpływ na odczuwaną wydajność jest znaczny.
Literatura pokrewna
- React 19.2 SSR Primitives: Activity, cacheSignal i PPR wyjaśnione — Dowiedz się, jak nowy komponent Activity, cacheSignal oraz Partial Pre-rendering w React 19.2 dają programistom bezpośrednią kontrolę nad wydajnością renderowania na serwerze.