A Guide to React Rendering Behaviour

Straight‑to‑the‑point patterns and anti‑patterns for preventing unnecessary re‑renders in your React applications—boost performance with composition, Context optimizations, React.memo, useMemo, and proper list key usage.

rahul sharma

3 months ago

a-guide-to-react-rendering-behaviour

Today, we're cutting straight to the chase—no fluff, no long explanations, just the good stuff. We're talking patterns to stop your React app from re‑rendering itself into oblivion. You will or have already encountered these if you’re a React developer.

Preventing re‑renders with composition
Creating components in render function
Creating components inside the render function of another component is an anti‑pattern and a major performance killer. On every re‑render React will re‑mount this component (destroy and re‑create it from scratch), which is much slower than a normal re‑render. You’ll also run into bugs like content flashing, state resets on every re‑render, loss of focus, and useEffect firing each time.

Moving the state down
When a large component contains a small UI element with its own state (e.g., a modal toggle), extract that state and UI into a separate, smaller component. Encapsulating the modal’s state, the dialog, and the trigger button keeps the heavy parent from re‑rendering when only the modal needs to update.

Children-as‑props pattern
Also called “wrap state around children.” Wrap slow, bulky portions of your render tree as children of a small, stateful wrapper. The wrapper manages state and only re‑renders itself; its children (passed as a prop) remain untouched by state changes.

Components-as‑props pattern
Similar to children-as‑props, but you pass entire components as props to a state‑managing wrapper. Use this when you have multiple heavy components that shouldn’t re‑render on every state change and can’t be grouped as a single children prop.

Preventing re‑renders caused by Context
Memoizing Provider value
If your Context Provider isn’t at the top level, memoize its value so consumers only re‑render when that value truly changes, not whenever the parent updates.

Splitting data and API
When a Context holds both data and setters/getters, split them into separate Providers. Components that only need the API won’t re‑render on data changes, and vice versa.

Preventing re‑renders with React.memo
Component with primitive values as props
Wrap a component in React.memo to skip re‑renders when its props stay the same. Ensure non‑primitive props (objects, arrays, functions) are themselves memoized via useMemo or useCallback.

React.memo: components as props or children
To optimize passed‑in components, apply React.memo directly to those components. Memoizing the parent won’t help because children and props are new objects on each render.

Preventing re‑renders with useMemo
Using useMemo for expensive calculations
Only employ useMemo for genuinely expensive computations—typically the creation of React elements (e.g., mapping large lists). Remember, useMemo itself has a cost, so don’t overuse it.

Improving re‑render performance of lists
The key attribute can make or break list rendering speed. Use a stable string (like an item’s id or a fixed index for static lists).

Don’t use random values as key
Random keys force React to re‑mount every item on each render, leading to poor performance and state/controlled‑component bugs.