
Part 1: React Rendering Demystified — What Actually Causes Re-Renders?
Published: 7/14/2025
Before optimizing React performance, you need to understand the “why” behind re-renders. This post is a deep dive into React’s rendering behavior, what triggers it, and how to control it like a pro.
Table of Contents
- What is a Re-render in React?
- The React Render Cycle
- What Triggers a Component to Re-render?
- Prop Drilling, Re-render Cascades, and Why It Hurts
- Reconciliation & Virtual DOM
- Practical Examples of Re-renders (with Logs)
- Key Insights for Part 2
What is a Re-render in React?
In simple terms, a re-render happens when React re-executes your component function to figure out what the updated UI should look like. This doesn’t always mean something changes in the actual DOM, but React still goes through the process of running the component and generating a new version of the UI.
During each re-render:
- The component function runs again
- All hooks are re-evaluated (useState, useEffect, etc.)
- React generates a new virtual DOM tree
- It compares the new virtual DOM to the previous one and updates only the parts of the actual DOM that have changed
The React render cycle explained
Here’s a simplified version of what happens when React renders a component:
- Initial render
React runs the component function, builds the virtual DOM, and mounts it to the real DOM. - A change occurs
For example, setState is called. - React re-runs the component
It creates a new virtual DOM from the updated function output. - Reconciliation
React compares the new virtual DOM to the previous one and figures out what changed. - DOM update
React applies the changes to the actual DOM efficiently.
This cycle repeats as your app interacts with the user or data updates.
What triggers a component to re-render
There are four main things that can trigger a re-render:
- State updates
If you call a state update function (like setCount), React re-renders that component. - Props change
If a parent component passes down new props, the child re-renders. - Context value changes
If a component uses a context and the context value changes, the component re-renders. - Parent re-renders
Even if props didn’t change, React will re-render the child by default if the parent re-renders.
This last point is especially important. Child components are not automatically optimized to skip re-renders unless you explicitly handle it.
Prop drilling, re-render cascades, and why it hurts
Prop drilling means passing data down through multiple levels of components — even if only the component at the bottom actually needs it.
Here’s an example:
<Parent>
<Middle>
<Child />
</Middle>
</Parent>
If the Parent has state that changes and is passed all the way down to Child, then every component in the chain (Parent, Middle, and Child) will re-render when that state updates.
In small apps, this usually isn’t noticeable. But in larger apps, especially when deep trees or expensive components are involved, this can slow things down.
Reconciliation and the virtual DOM
Reconciliation is how React compares the old and new versions of your UI and updates only what’s different.
React doesn’t update the real DOM directly every time something changes. Instead, it uses a virtual DOM — a lightweight, in-memory representation of the UI.
On every re-render:
- React builds a new virtual DOM tree
- It compares this new tree with the previous one using a diffing algorithm
- It calculates the minimal number of changes
- Only those changes are applied to the real DOM
This makes React very efficient — but the component still has to re-run to generate the virtual DOM. So even if no DOM updates are made, unnecessary renders still add overhead.
Real-world examples of re-renders using logs
Let’s take a simple example:
function Parent() {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(count + 1)}>Increment</button>
<Child />
</>
);
}
function Child() {
console.log('Child rendered');
return <p>I’m a child component</p>;
}
Every time you click the button, Parent re-renders because its state changes. That causes Child to re-render too — even though it doesn’t use the count state at all.
This is the default behavior in React. Unless you prevent it using tools like React.memo, children will always re-render when their parent does.
To observe this yourself, open the browser console and interact with the button. You’ll see "Child rendered" logged every time.
Key insights leading into Part 2
Here’s what to take away from this post:
- A re-render happens whenever state, props, or context change — or when a parent component re-renders.
- React is smart about updating the real DOM, but the component function still runs every time.
- Unnecessary re-renders can add up and affect performance, especially in larger apps.
- You can start debugging render behavior with console logs, React DevTools, or libraries like why-did-you-render.
In Part 2, I’ll go over how to reduce these unnecessary renders using memoization, pure components, and other practical techniques you can apply in any project.
