React Re-render Explained
Learn why React re-renders components including and what causes it. We will also go over parent and child component re-renders.
Table of Contents 📖
- What is a React Re-render?
- React Re-render and Component Children
- React Re-render and Component Parents
- Are React Re-renders Bad?
What is a React Re-render?
A React re-render is when a component that is already displayed is rendered again. The core reason for every re-render is a state change. React re-renders components to keep the UI in sync with the state. Therefore, when the state of a component changes, the component is re-rendered to match the UI to the new state.
import {useState} from 'react';
const App = () => {
console.log('Rendering App');
const [count, setCount] = useState(0);
return (
<>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</>
);
};
export default App;
In the code above, whenever we click the button, the App component's state is updated. As a result, React re-renders the App component so that the UI matches the new state.
React Re-render and Component Children
When a component is re-rendered, so are all of the component's children.
import {useState} from 'react';
const CounterDisplay = ({count}) => {
console.log('Rendering CounterDisplay');
return (
<div>
<p>Count: {count}</p>
</div>
);
};
const App = () => {
console.log('Rendering App');
const [count, setCount] = useState(0);
return (
<>
<CounterDisplay count={count} />
<button onClick={() => setCount(count + 1)}>Increment</button>
</>
);
};
export default App;
Clicking the button in the App component changes the App component's state causing it to re-render. As the CounterDisplay component is a child of the App component, it is also re-rendered. Even if a child component does not receive any props, it will still re-render.
import {useState} from 'react';
const CounterDisplay = ({count}) => {
console.log('Rendering CounterDisplay');
return (
<div>
<p>Count: {count}</p>
</div>
);
};
const NoPropsComponent = () => {
console.log('Rendering NoPropsComponent');
return (
<p>No Props Component</p>
);
};
const App = () => {
console.log('Rendering App');
const [count, setCount] = useState(0);
return (
<>
<NoPropsComponent />
<CounterDisplay count={count} />
<button onClick={() => setCount(count + 1)}>Increment</button>
</>
);
};
export default App;
Here, clicking the button and changing the App component's state causes the NoPropsComponent to re-render even though it does not receive any props. React does this because it does not know for certain if the NoPropsComponent depends on the count state. React errs on the side of caution by expecting a component to be impure, meaning that the component could produce a different UI even with the same props. For example, imagine if our NoPropsComponent displayed the current time.
const NoPropsComponent = () => {
console.log('Rendering NoPropsComponent');
return (
<p>{new Date().toString()}</p>
);
};
If the component was not re-rendered, then the component would not be updated with the current time.
React Re-render and Component Parents
Unlike a component's children, when a component's state changes, its parents are not re-rendered.
import {useState} from 'react';
const CounterDisplay = () => {
const [count, setCount] = useState(0);
console.log('Rendering CounterDisplay');
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
const App = () => {
console.log('Rendering App');
return (
<CounterDisplay />
);
};
export default App;
Here, the count state is moved into the CounterDisplay component. When the count state changes the CounterDisplay component is re-rendered to match the new state but its parent, the App component, is not.
Are React Re-renders Bad?
React re-rendering is not inherently bad as it is often necessary. Furthermore, re-rendering is a lot quicker than a lot of developers think. However, the unnecessary and frequent re-rendering of large components can cause performance issues.