Why Does React Re-render?

Why Does React Re-render? A Simple Explanation for Developers
When I first started working with React, I didn’t fully understand why React re-renders components. Like many developers, I knew enough to get by, but when someone asked, "What triggers a re-render?", I couldn’t explain it properly. 😅
This confusion is common, but understanding React’s render cycle is important, especially if you want to optimize performance using tools like React.memo
or useCallback
.
In this blog, let's break down when and why React re-renders, and how you can avoid unnecessary re-renders for better performance.
The Core React Re-rendering Process
Every re-render in React starts with a state change. This means that whenever a component’s state is updated, React will re-render that component, and all its child components (descendants).
Example:
Let’s look at this example:
function App() { return ( <> <Counter /> <footer>© 2022 Big Count Inc.</footer> </> ); } function Counter() { const [count, setCount] = React.useState(0); return ( <main> <BigCountNumber count={count} /> <button onClick={() => setCount(count + 1)}>Increment</button> </main> ); } function BigCountNumber({ count }) { return <p>Count: {count}</p>; }
In this example:
- The
Counter
component owns thecount
state. - When the state changes (e.g., when the user clicks the "Increment" button), only the
Counter
and its child componentBigCountNumber
re-render.
Notice that the App
component does not re-render, even though it is the parent component. React only re-renders components that are directly affected by the state change and their children.
The Truth About Props and Re-renders
Many developers think that React re-renders a component just because its props change. But this isn’t the full story.
Let’s update our example by adding a new component Decoration
:
function Decoration() { return <div>⛵️</div>; } function Counter() { const [count, setCount] = React.useState(0); return ( <main> <BigCountNumber count={count} /> <button onClick={() => setCount(count + 1)}>Increment</button> <Decoration /> </main> ); }
Now, Decoration
doesn’t depend on the count
prop, so it seems like it shouldn’t re-render. But React will still re-render it because, when the state in the parent Counter
changes, React doesn’t know for sure if the Decoration
component depends on that state.
Key takeaway: When a parent component re-renders, React will re-render all of its child components, even if those child components don’t use the updated state directly.
Using React.memo
to Avoid Unnecessary Re-renders
If we don’t want to re-render certain components unnecessarily, we can use React.memo
. This allows React to skip re-rendering a component if its props haven’t changed.
Here’s how you can use React.memo
for the Decoration
component:
const Decoration = React.memo(() => { return <div>⛵️</div>; });
Now, Decoration
will only re-render if its props change. If its props stay the same, React will reuse the previous render and save performance.
How React Handles Context and Re-renders
If you use React Context, it works similarly to props. If a context value changes, all components that use that context will re-render.
However, context is like an invisible prop. If a component is consuming context (using useContext
), React treats it the same as if it were receiving a prop. So, if the context value changes, the component will re-render to reflect the updated state.
How to Track Re-renders with React DevTools
In real-world applications, it can be hard to figure out why a component re-rendered. For this, React DevTools can be really helpful. You can enable the “Highlight Updates” feature to see exactly which components re-rendered.
This is especially useful when trying to figure out performance bottlenecks in your app.
Final Thoughts
Understanding why React re-renders is key to writing efficient, optimized code. Here are the key takeaways:
- React re-renders a component and all its descendants when the component’s state changes.
- Changing props doesn’t automatically cause re-renders unless the props actually change.
- Use
React.memo
to avoid unnecessary re-renders for pure components. - React DevTools can help you track and debug re-renders.