State-wijzigingen triggeren re-renders, en slecht-gestructureerde state kan veel meer re-rendering veroorzaken dan nodig — wat de app vertraagt. De sleutelstrategieën: smal abonneren, state splitsen, memoization, en state lokaal houden.
1. Abonneer je op het minimale slice dat je nodig hebt
// ❌ subscribing to the whole store → re-renders on ANY change
const store = useStore();
const count = store.count;
// ✅ select only what you use → re-renders only when `count` changes
const count = useStore((s) => s.count);
Selectieve abonnementen (Zustand/Redux selectors, Jotai atoms) zijn de grootste hefboom — componenten re-renderen alleen als hun specifieke slice verandert, niet bij elke store-update.
2. Split state / context om blast radius te beperken
// ❌ one big context → every consumer re-renders when anything changes
// ✅ separate contexts so unrelated updates don't cross-trigger
<ThemeContext><UserContext>...</UserContext></ThemeContext>
3. Memoize componenten en waarden
const Item = React.memo(ItemComponent); // skip re-render if props are unchanged
const expensiveValue = useMemo(() => compute(data), [data]);
const handleClick = useCallback(() => doX(id), [id]); // stable function reference
Memoization voorkomt dat kinderen re-renderen wanneer hun props (per referentie) niet zijn veranderd — maar het werkt alleen als je ook props/callbacks referentieel stabiel houdt (vandaar useCallback/useMemo) en state immutable update.
4. Hou state zo lokaal mogelijk
State high in the tree re-renders everything below it.
Move state DOWN to the smallest component that needs it → smaller re-render scope.
5. Bewaar geen afgeleide waarden; vermijd nieuwe referenties per render
// ❌ a new object/array each render breaks memoization downstream
<Child config={{ a: 1 }} /> // new {} every render
// ✅ stable reference
const config = useMemo(() => ({ a: 1 }), []);
6. Gebruik gememoiseerde selectors voor afgeleide data
const selectActive = createSelector([s => s.items], items => items.filter(i => i.active));
// returns the SAME reference when items didn't change → no needless re-render
Meet eerst
React DevTools Profiler / "why did you render" → find what actually re-renders
before optimizing. Premature memoization adds complexity for no gain.
Waarom het belangrijk is
Excessieve re-renders zijn een voorkomende oorzaak van trage React/state-driven apps, en ze ontstaan door hoe state is gestructureerd en geabonneerd.
De toolkit — smalte selectieve abonnementen, gesplitste contexts, memoization met stabiele referenties, immutable updates, en lokaliseren van state — controleert rechtstreeks de re-render scope.
Belangrijkst is dat je moet meten (Profiler) om de echte bottleneck te vinden voordat je optimaliseert, omdat onvoorzichtige memoization complexiteit toevoegt zonder voordeel.
Begrijpen wat re-renders triggert en hoe je ze in toom houdt, is essentieel voor performante apps op grote schaal.
