Cascade de re-rendus React : quand un clic re-rend tout l'arbre
Ce qui se passe
En React, une mise à jour d'état re-rend le composant et, par défaut, tous ses enfants. Si l'état vit haut dans l'arbre (un context, un store au niveau de la page), une seule frappe ou un seul clic peut re-rendre des centaines de composants — dont la plupart affichent exactement la même chose qu'avant.
Chaque rendu est peu coûteux ; des milliers dans un seul gestionnaire ne le sont pas. Le travail tombe dans la phase de processing time de l'INP.
Comment le reconnaître
- Le Profiler de React DevTools montre de larges flame graphs : des composants se re-rendent sans que leurs props changent visiblement.
- Taper dans un input contrôlé est saccadé ; chaque frappe re-rend de grandes listes ou tables.
- Le processing time domine l'INP, et la pile dans DevTools Performance est pleine d'internals React.
Comment corriger
- Descendez l'état : gardez-le dans le plus petit composant qui en a besoin plutôt que dans un composant au niveau de la page ou un context.
- Enveloppez les sous-arbres coûteux dans React.memo et stabilisez les props que vous leur passez avec useCallback/useMemo — memo est inutile si un nouveau callback est créé à chaque rendu.
- Marquez les mises à jour non urgentes (filtrer une liste pendant la saisie) avec useTransition pour que le rendu urgent (l'input lui-même) soit peint en premier.
Problème
const Page = () => {
const [query, setQuery] = useState("")
// every keystroke re-renders Page → Header, Sidebar, BigTable, Footer
return <>
<SearchInput value={query} onChange={setQuery} />
<BigTable rows={filterRows(rows, query)} />
</>
}
Correctif
const BigTable = React.memo(({ rows }) => /* ... */)
const Page = () => {
const [query, setQuery] = useState("")
const [isPending, startTransition] = useTransition()
const rows = useMemo(() => filterRows(allRows, query), [query])
const onChange = (q) =>
startTransition(() => setQuery(q)) // input paints first, table follows
return <>
<SearchInput onChange={onChange} />
<BigTable rows={rows} />
</>
}
Analysez votre site gratuitement →