Join the discussion
Comments
Loading comments...
Cookie preferences
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Join the discussion
Loading comments...
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Comment React groupe plusieurs appels setState en un seul re-rendu pour la performance.
Le groupement d'état signifie que React collecte plusieurs appels setState d'un même bloc synchrone et les traite tous en une seule passe de re-rendu. Au lieu de re-rendre après chaque setState individuel, React attend la fin du 'lot' courant, applique toutes les mises à jour d'un coup et effectue exactement un seul rendu. React 18 a étendu le groupement automatique pour couvrir également le code asynchrone et les écouteurs d'événements natifs.
Lorsque vous appelez setA(1) et setB(2) dans un gestionnaire de clic, React ne re-rend pas immédiatement après setA. Il met en file d'attente les deux mises à jour et planifie un seul re-rendu. Votre composant s'affiche une fois avec les deux nouvelles valeurs appliquées.
Chaque appel setState ajoute un objet Update à la file circulaire du hook. React marque le fiber comme ayant du travail en attente et planifie une microtâche (ou un callback) pour vider la file — mais seulement après la fin du code synchrone courant.
Dans React 17, le groupement se produisait uniquement à l'intérieur des gestionnaires d'événements React. Les appels setState à l'intérieur de setTimeout, Promises ou callbacks fetch déclenchaient des re-rendus individuels. React 18 groupe TOUTES les mises à jour automatiquement, quelle que soit leur origine.
Si vous avez besoin d'une mise à jour DOM synchrone (p. ex. pour mesurer la mise en page après un changement de state), appelez ReactDOM.flushSync(() => setState(...)). Cela force React à vider la mise à jour immédiatement et de manière synchrone, contournant le groupement.
Lorsque plusieurs appels setState dépendent de la valeur précédente, utilisez la forme fonctionnelle : setState(prev => prev + 1). React applique ces mises à jour dans l'ordre de la file, donc chaque mise à jour voit le résultat de la précédente — pas la valeur au moment du rendu.
Fonctionnalité React 18 : tous les appels setState sont groupés ensemble, même à l'intérieur de setTimeout, Promises et écouteurs d'événements natifs. Réduit les re-rendus inutiles.
Une liste chaînée circulaire sur chaque objet hook qui stocke les appels setState en attente. Vidée à la fin de chaque lot — toutes les mises à jour appliquées dans l'ordre.
Force React à vider les mises à jour d'état en attente de manière synchrone et immédiate. Contourne le groupement. À utiliser uniquement lorsque vous avez besoin d'une mesure DOM après un changement de state.
setState(prev => newValue). Garantit de recevoir la dernière valeur du state, même lorsque les mises à jour sont groupées ou mises en file de manière asynchrone.
Le groupement réduit le nombre de rendus. Sans groupement : N appels setState = N rendus. Avec groupement : N appels setState = 1 rendu.
1// React 18: ALL of these batch into 1 render23// Inside event handler (always batched)4function handleClick() {5 setCount(c => c + 1); // queued6 setFlag(true); // queued7 setName('Alice'); // queued8 // 1 render happens here9}1011// Inside setTimeout — NOW also batched in React 1812setTimeout(() => {13 setCount(c => c + 1); // queued14 setFlag(true); // queued15 // 1 render (React 17 would have triggered 2!)16}, 0);1718// Opt out of batching when needed:19import { flushSync } from 'react-dom';20flushSync(() => setCount(1)); // renders immediately21flushSync(() => setFlag(true)); // renders again22// 2 renders total
Le groupement est l'une des optimisations de performance les plus importantes de React. Sans lui, une seule interaction utilisateur déclenchant 3 mises à jour de state provoquerait 3 cycles complets rendu + réconciliation + commit. Avec le groupement, c'est toujours juste 1. Le groupement automatique de React 18 est particulièrement précieux pour le code asynchrone — les réponses serveur, les messages WebSocket et les timers ne saturent plus le moteur de rendu.
A login form validates email, password, and shows/hides error messages. The submit handler calls `setEmailError(...)`, `setPasswordError(...)`, `setIsSubmitting(false)` — three state updates that should be a single render.
In React 17, calling setState inside setTimeout or fetch().then() didn't batch — each call triggered a separate render. Users would see a flash: first the email error appears, then the password error, then the loading spinner disappears. Three renders for one validation check.
React 18's automatic batching ensures all three setState calls result in ONE render, regardless of whether they're inside an event handler, setTimeout, fetch callback, or promise. The user sees all errors and the stopped spinner simultaneously — no flash.
Takeaway: React 18's automatic batching is a free performance upgrade for existing code. If you migrated from React 17 and had flushSync workarounds for batching, you can now remove them — batching works everywhere automatically.
You need to update a component's state and immediately measure the resulting DOM height to pass to a third-party animation library. With batching, the DOM hasn't updated yet when you try to measure.
Automatic batching defers the DOM update. After calling `setExpanded(true)`, the DOM still shows the collapsed state. Measuring `element.offsetHeight` returns the old height. The animation library receives the wrong value.
Wrap the state update in `flushSync()`: `flushSync(() => setExpanded(true))`. This forces React to immediately commit the DOM update synchronously. The next line can safely measure `element.offsetHeight` and get the expanded height. Use sparingly — it opts out of batching's performance benefit.
Takeaway: flushSync is the escape hatch when you need synchronous DOM access after a state update. Common use cases: third-party animation libraries, scroll position restoration, and focus management. Use it only when batching conflicts with imperative DOM operations.