Szybkość reakcji zaczyna się od uporządkowania drzewa komponentów
Ponowne renderowanie nie jest wrogiem – wrogiem jest szerokie rozprzestrzenianie się stanów. Przenieś źródła w kierunku liści przed mikroprzechowywaniem.
React robi to, czego wymaga projekt drzewa. Gdy aplikacja wydaje się wolna, framework często podąża za długą ścieżką propagacji stanu/aktualizacji – a nie zawodzi w tajemniczy sposób.
Ponowne renderowanie to nie wróg
Renderowanie zapewnia spójność interfejsu użytkownika. Wrógem są niepotrzebne operacje w dużych poddrzewach przy każdym naciśnięciu klawisza.
// ❌ count lives in Parent — expensive siblings re-render on every click
function Parent() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
<ExpensiveComponent />
<AnotherExpensiveComponent />
</div>
);
}
// ✅ count lives in Counter — expensive siblings are untouched
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
);
}
function Parent() {
return (
<div>
<Counter />
<ExpensiveComponent />
<AnotherExpensiveComponent />
</div>
);
}
// ❌ SearchLayout owns state — ExpensiveList re-renders on every keystroke
function SearchLayout() {
const [query, setQuery] = useState('');
return (
<div>
<input value={query} onChange={e => setQuery(e.target.value)} />
<ExpensiveList />
</div>
);
}
/* ✅ StatefulInput receives expensive content as children
— its reference stays stable */
function StatefulInput({ children }) {
const [query, setQuery] = useState('');
return (
<div>
<input value={query} onChange={e => setQuery(e.target.value)} />
{children}
</div>
);
}
function SearchLayout() {
return (
<StatefulInput>
<ExpensiveList />
</StatefulInput>
);
}
Gdzie propagacja powinna się zatrzymać
Przeniesienie źródła
Zachowaj stan obok komponentów, które go zapisują i odczytują. Tekst roboczy formularza nie musi znajdować się u korzenia aplikacji.
Blokowanie ścieżki
Dzieci, które przyjmują stabilne właściwości, mogą uniknąć problemów. Kompozycja oraz wykorzystanie dzieci jako slotów często przewyższają metodę powszechnego memoizowania.
Drzewo jako decyzja projektowa
Organizacja to wybór architektoniczny: foldery z funkcjami, podział na kontenery i elementy prezentacyjne oraz lokalni dostawcy ograniczają zasięg wpływu aktualizacji.
Początek od drzewa
Zanim zaczniesz stosować mikrooptymalizacje, narysuj schemat pokazujący, który stan powinien znajdować się gdzie oraz które poddrzewa muszą pozostać niewzruszone podczas częstych aktualizacji. Większość skarg typu „React jest wolny” dotyczy właśnie struktury drzewa.
Najpierw sprawdź profil wydajności, potem przearanżuj strukturę; pamięć podręczną stosuj na końcu.
Dostawcy kontekstu są częścią drzewa: mega-kontekst, który zmienia się przy każdym renderowaniu, unieważnia pamięć podręczną liści. Dziel konteksty według częstotliwości aktualizacji.
Dzielenie kodu na poziomie tras zmniejsza rozmiar drzewa, za które płacisz przy pierwszym odświeżeniu; łącz je z lokalnym stanem, aby nawigacja była lekka.
Wirtualizacja list to swego rodzaju operacja chirurgiczna na drzewie – usuwaj wiersze poza ekranem zamiast próbować synchronizować tysiące nieaktywnych węzłów.
Własność dokumentu: która zespołowa grupa odpowiada za stan danego poddrzewa. Wspólne globalne magazyny powodują ten sam problem szerokiej propagacji, tylko pod inną nazwą.
Wykorzystaj funkcję pomiaru czasu wykonywania operacji commit w React Profiler przed i po zmianie stanu; zachowaj różnice w PR do przeglądania.
Komponenty serwerowe i klientowe zmieniają lokalizację drzewa, ale zasady propagacji nadal obowiązują na obszarze klientowym.
Dostawcy kontekstu są częścią drzewa: mega-kontekst, który zmienia się przy każdym renderowaniu, unieważnia efekt memoizacji liści. Dziel konteksty według częstotliwości aktualizacji.
Dzielenie kodu na poziomie tras zmniejsza rozmiar drzewa, za które płacisz przy pierwszym narysowaniu; łącz je z lokalnym stanem, aby nawigacje były szybkie.
Wirtualizacja list to swego rodzaju „chirurgia drzewa” – usuwaj wiersze poza ekranem zamiast synchronizować tysiące nieaktywnych węzłów.
Własność dokumentu: która zespołowa grupa odpowiada za stan danego poddrzewa. Wspólne globalne magazyny powodują ten sam problem szerokiej propagacji, tylko pod inną nazwą.
Wykorzystaj funkcję pomiaru czasu wykonywania operacji commit w React Profiler przed i po zmianie stanu; zachowaj różnice w PR do przeglądania.
Komponenty serwerowe i klientowe zmieniają lokalizację drzewa, ale zasady propagacji nadal obowiązują na obszarze klientowym.
Dostawcy kontekstu są częścią drzewa: mega-kontekst, który zmienia się przy każdym renderowaniu, unieważnia efekt memoizacji liści. Dziel konteksty według częstotliwości aktualizacji.
Dzielenie kodu na poziomie tras zmniejsza rozmiar drzewa, za które płacisz przy pierwszym narysowaniu; łącz je z lokalnym stanem, aby nawigacje były szybkie.
Wirtualizacja list to swego rodzaju „chirurgia drzewa” – usuwaj wiersze poza ekranem zamiast synchronizować tysiące nieaktywnych węzłów.
Własność dokumentu: która zespołowa grupa odpowiada za stan danego poddrzewa. Wspólne globalne magazyny powodują ten sam problem szerokiej propagacji, tylko pod inną nazwą.
Wykorzystaj funkcję pomiaru czasu wykonywania operacji commit w React Profiler przed i po zmianie stanu; zachowaj różnice w PR do przeglądania.
Komponenty serwerowe i klientowe zmieniają lokalizację drzewa, ale zasady propagacji nadal obowiązują na obszarze klientowym.
Dostawcy kontekstu są częścią drzewa: mega-kontekst, który zmienia się przy każdym renderowaniu, unieważnia efekt memoizacji liści. Dziel konteksty według częstotliwości aktualizacji.
Dzielenie kodu na poziomie tras zmniejsza rozmiar drzewa, za które płacisz przy pierwszym narysowaniu; łącz je z lokalnym stanem, aby nawigacje były szybkie.
Wirtualizacja list to swego rodzaju „chirurgia drzewa” – usuwaj wiersze poza ekranem zamiast synchronizować tysiące nieaktywnych węzłów.
Własność dokumentu: która zespołowa grupa odpowiada za stan danego poddrzewa. Wspólne globalne magazyny powodują ten sam problem szerokiej propagacji, tylko pod inną nazwą.
Wykorzystaj funkcję pomiaru czasu wykonywania operacji commit w React Profiler przed i po zmianie stanu; zachowaj różnice w PR do przeglądania.
Komponenty serwerowe i klientowe zmieniają lokalizację drzewa, ale zasady propagacji nadal obowiązują na obszarze klientowym.
Dostawcy kontekstu są częścią drzewa: mega-kontekst, który zmienia się przy każdym renderowaniu, unieważnia efekt memoizacji liści. Dziel konteksty według częstotliwości aktualizacji.
Dzielenie kodu na poziomie tras zmniejsza rozmiar drzewa, za które płacisz przy pierwszym narysowaniu; łącz je z lokalnym stanem, aby nawigacje były szybkie.
Wirtualizacja list to swego rodzaju „chirurgia drzewa” – usuwaj wiersze poza ekranem zamiast synchronizować tysiące nieaktywnych węzłów.
Własność dokumentu: która zespołowa grupa odpowiada za stan danego poddrzewa. Wspólne globalne magazyny powodują ten sam problem szerokiej propagacji, tylko pod inną nazwą.
Wykorzystaj funkcję pomiaru czasu wykonywania operacji commit w React Profiler przed i po zmianie stanu; zachowaj różnice w PR do przeglądania.
Komponenty serwerowe i klientowe zmieniają lokalizację drzewa, ale zasady propagacji nadal obowiązują na obszarze klientowym.
Dostawcy kontekstu są częścią drzewa: mega-kontekst, który zmienia się przy każdym renderowaniu, unieważnia efekt memoizacji liści. Dziel konteksty według częstotliwości aktualizacji.
Dzielenie kodu na poziomie tras zmniejsza rozmiar drzewa, za które płacisz przy pierwszym narysowaniu; łącz je z lokalnym stanem, aby nawigacje były szybkie.
Wirtualizacja list to swego rodzaju „chirurgia drzewa” – usuwaj wiersze poza ekranem zamiast synchronizować tysiące nieaktywnych węzłów.
Własność dokumentu: która zespołowa grupa odpowiada za stan danego poddrzewa. Wspólne globalne magazyny powodują ten sam problem szerokiej propagacji, tylko pod inną nazwą.
Wykorzystaj funkcję pomiaru czasu wykonywania operacji commit w React Profiler przed i po zmianie stanu; zachowaj różnice w PR do przeglądania.
Komponenty serwerowe i klientowe zmieniają lokalizację drzewa, ale zasady propagacji nadal obowiązują na obszarze klientowym.
Dostawcy kontekstu są częścią drzewa: mega-kontekst, który zmienia się przy każdym renderowaniu, unieważnia efekt memoizacji liści. Dziel konteksty według częstotliwości aktualizacji.
Dzielenie kodu na poziomie tras zmniejsza rozmiar drzewa, za które płacisz przy pierwszym narysowaniu; łącz je z lokalnym stanem, aby nawigacje były szybkie.
Wirtualizacja list to swego rodzaju „chirurgia drzewa” – usuwaj wiersze poza ekranem zamiast synchronizować tysiące nieaktywnych węzłów.
Własność dokumentu: która zespołowa grupa odpowiada za stan danego poddrzewa. Wspólne globalne magazyny powodują ten sam problem szerokiej propagacji, tylko pod inną nazwą.
Wykorzystaj funkcję pomiaru czasu wykonywania operacji commit w React Profiler przed i po zmianie stanu; zachowaj różnice w PR do przeglądania.
Komponenty serwerowe i klientowe zmieniają lokalizację drzewa, ale zasady propagacji nadal obowiązują na obszarze klientowym.
Dostawcy kontekstu są częścią drzewa: mega-kontekst, który zmienia się przy każdym renderowaniu, unieważnia efekt memoizacji liści. Dziel konteksty według częstotliwości aktualizacji.
Dzielenie kodu na poziomie tras zmniejsza rozmiar drzewa, za które płacisz przy pierwszym narysowaniu; łącz je z lokalnym stanem, aby nawigacje były szybkie.
Wirtualizacja list to swego rodzaju „chirurgia drzewa” – usuwaj wiersze poza ekranem zamiast synchronizować tysiące nieaktywnych węzłów.
Własność dokumentu: która zespołowa grupa odpowiada za stan danego poddrzewa. Wspólne globalne magazyny powodują ten sam problem szerokiej propagacji, tylko pod inną nazwą.
Wykorzystaj funkcję pomiaru czasu wykonywania operacji commit w React Profiler przed i po zmianie stanu; zachowaj różnice w PR do przeglądania.
Komponenty serwerowe i klientowe zmieniają lokalizację drzewa, ale zasady propagacji nadal obowiązują w obszarze klientowym.
Dostawcy kontekstu są częścią drzewa: mega-kontekst, który zmienia się przy każdym renderowaniu, unieważnia efekt memoizacji liści. Dziel konteksty według częstotliwości aktualizacji.
Dzielenie kodu na poziomie tras zmniejsza rozmiar drzewa, za który płacisz przy pierwszym narysowaniu; łącz je z lokalnym stanem, aby nawigacje były szybkie.
Dostawcy, które aktualizują się przy każdym naciśnięciu klawisza, powinny otaczać jedynie te komponenty, które wymagają takiej częstotliwości – a nie całą strukturę strony.
Dane pochodne powinny znajdować się w selektorach lub zapisanych dzieciach, a nie być odzwierciedlane w stanie rodzeństwa, co powoduje większą liczbę renderowań.
Zwizualizuj drzewo: narysuj prostokąty dla właścicieli stanu i strzałki dla propów. Szerokie rozgałęzienia od korzenia to typowy objaw problemu.
Funkcje równoległe pomagają w radzeniu sobie z pilnymi sytuacjami, ale nie mogą naprawić „boga-komponentu”, który kontroluje każde pole złożonego interfejsu.
Taktyka migracji: przenieś jedną liść na niższy poziom drzewa za każdym PR, używając narzędzia do analizy wydajności przed i po zmianie.
Dostawcy, którzy aktualizują się przy każdym naciśnięciu klawisza, powinni obejmować tylko te komponenty, które wymagają takiej częstotliwości aktualizacji – a nie całą strukturę strony.
Dane pochodne powinny znajdować się w selektorach lub zapisanych dzieciach, a nie być odzwierciedlane w stanie rodzeństwa, co powoduje większą liczbę renderowań.
Zwizualizuj drzewo: narysuj prostokąty dla właścicieli stanu i strzałki dla propów. Szerokie rozgałęzienia od korzenia to typowy objaw problemu.
Funkcje równoległe pomagają w radzeniu sobie z pilnością, ale nie mogą naprawić „boga-komponentu”, który kontroluje każde pole złożonego interfejsu.
Taktyka migracji: przenieś jedną „wyspę stanu” w kierunku liściowym przy każdym PR, używając narzędzia do analizy wydajności przed i po jej dodaniu.
Dostawcy, którzy aktualizują się przy każdym naciśnięciu klawisza, powinni obejmować tylko te komponenty konsumujące, które wymagają takiej częstotliwości – a nie całą strukturę strony.
Dane pochodne powinny znajdować się w selektorach lub zapisanych dzieciach komponentów, a nie być odzwierciedlane w stanach braciowych, co powoduje większą liczbę renderowań.
Wizualizuj drzewo: narysuj prostokąty dla właścicieli stanów i strzałki dla ich atrybutów. Szerokie rozgałęzienia od korzenia to zwykły objaw problemów.
Funkcje równoległe pomagają w radzeniu sobie z pilnością, ale nie mogą naprawić „boga-komponentu”, który kontroluje każde pole złożonego interfejsu.
Taktyka migracji: przenieś jedną „wyspę stanu” w kierunku liściowym przy każdym PR, używając narzędzia do analizy wydajności przed i po jej dodaniu.
Dostawcy, którzy aktualizują się przy każdym naciśnięciu klawisza, powinni obejmować jedynie te komponenty konsumujące, które wymagają takiej częstotliwości – a nie całą strukturę strony.
Dane pochodne powinny znajdować się w selektorach lub zapisanych komponentach dziecięcych, a nie być odzwierciedlane w stanach elementów rodzinnych, co powoduje większą liczbę renderowań.
Wizualizuj drzewo: narysuj prostokąty dla właścicieli stanu oraz strzałki dla atrybutów. Szerokie rozgałęzienia od korzenia to typowy objaw takiej struktury.
Literatura pokrewna
- Przestań synchronizować stan z useEffect: bezpieczniejszy pattern w React — Dowiedz się, dlaczego używanie useEffect do synchronizacji stanu pochodnego powoduje sytuacje konkurencyjne i dodatkowe renderowania, oraz jak zastąpić to metodą wytwarzania danych w czasie renderowania i atrybutem key.