DEV Community

Nadia Makarevich
Nadia Makarevich

Posted on • Updated on

React re-renders guide: why React components re-render

Image description

Originally published at https://www.developerway.com. The website has more articles like this 😉


This is part 1 & part 2 of the full guide on React re-renders. The guide explains what are re-renders, what is necessary and unnecessary re-render, what can trigger a React component re-render.

The full guide also includes the most important patterns that can help prevent re-renders and a few anti-patterns that lead to unnecessary re-renders and poor performance as a result. Every pattern and antipattern is accompanied by visual aid and working code example.

Full guide table of content:


What is re-render in React?

When talking about React performance, there are two major stages that we need to care about:

  • initial render - happens when a component first appears on the screen
  • re-render - second and any consecutive render of a component that is already on the screen

Re-render happens when React needs to update the app with some new data. Usually, this happens as a result of a user interacting with the app or some external data coming through via an asynchronous request or some subscription model.

Non-interactive apps that don’t have any asynchronous data updates will never re-render, and therefore don’t need to care about re-renders performance optimization.

🧐 What is a necessary and unnecessary re-render?

Necessary re-render - re-render of a component that is the source of the changes, or a component that directly uses the new information. For example, if a user types in an input field, the component that manages its state needs to update itself on every keystroke, i.e. re-render.

Unnecessary re-render - re-render of a component that is propagated through the app via different re-renders mechanisms due to either mistake or inefficient app architecture. For example, if a user types in an input field, and the entire page re-renders on every keystroke, the page has been re-rendered unnecessarily.

Unnecessary re-renders by themselves are not a problem: React is very fast and usually able to deal with them without users noticing anything.

However, if re-renders happen too often and/or on very heavy components, this could lead to user experience appearing “laggy”, visible delays on every interaction, or even the app becoming completely unresponsive.


When React component re-renders itself?

There are four reasons why a component would re-render itself: state changes, parent (or children) re-renders, context changes, and hooks changes. There is also a big myth: that re-renders happen when the component’s props change. By itself, it’s not true (see the explanation below).

🧐 Re-renders reason: state changes

When a component’s state changes, it will re-render itself. Usually, it happens either in a callback or in useEffect hook.

State changes are the “root” source of all re-renders.

See example in codesandbox

Image description

🧐 Re-renders reason: parent re-renders

A component will re-render itself if its parent re-renders. Or, if we look at this from the opposite direction: when a component re-renders, it also re-renders all its children.

It always goes “down” the tree: the re-render of a child doesn’t trigger the re-render of a parent. (There are a few caveats and edge cases here, see the full guide for more details: The mystery of React Element, children, parents and re-renders).

See example in codesandbox

Image description

🧐 Re-renders reason: context changes

When the value in Context Provider changes, all components that use this Context will re-render, even if they don’t use the changed portion of the data directly. Those re-renders can not be prevented with memoization directly, but there are a few workarounds that can simulate it (see Part 7: preventing re-renders caused by Context).

See example in codesandbox

Image description

🧐 Re-renders reason: hooks changes

Everything that is happening inside a hook “belongs” to the component that uses it. The same rules regarding Context and State changes apply here:

  • state change inside the hook will trigger an unpreventable re-rerender of the “host” component
  • if the hook uses Context and Context’s value changes, it will trigger an unpreventable re-rerender of the “host” component

Hooks can be chained. Every single hook inside the chain still “belongs” to the “host” component, and the same rules apply to any of them.

See example in codesandbox

Image description

⛔️ Re-renders reason: props changes (the big myth)

It doesn’t matter whether the component’s props change or not when talking about re-renders of not memoized components.

In order for props to change, they need to be updated by the parent component. This means the parent would have to re-render, which will trigger re-render of the child component regardless of its props.

See example in codesandbox

Only when memoization techniques are used (React.memo, useMemo), then props change becomes important.

Image description


See the rest of the guide here:


Originally published at https://www.developerway.com. The website has more articles like this 😉

Subscribe to the newsletter, connect on LinkedIn or follow on Twitter to get notified as soon as the next article comes out.

Latest comments (7)

Collapse
 
lovetingyuan profile image
tingyuan

github.com/lovetingyuan/react-atom...
This library can help solve unnecessary re-renders caused by React Context and allows fine-grained control over the reading and writing of each property.

Collapse
 
sufianbabri profile image
Sufian Babri • Edited

Excellent article especially those codesandbox links to play around for getting even clearer picture.

If I summarize the difference between context and hook changes:

Unless the Context Provider's value is memoized, it has a potential to be worse than a hook change.

Again, it's a excellent article which explains things without unnecessarily trying to impress the readers.

Collapse
 
chideracode profile image
Chidera Humphrey

Very insightful.

Thanks a lot

Collapse
 
aderchox profile image
aderchox

This was amazing, thanks!

Collapse
 
anasnmu profile image
Anas Nabil

Thanks for sharing this solid article, keep going

Collapse
 
fjones profile image
FJones

Minor nitpick: The mere existence of useState is not a state change. It's the setState call that actually changes the state. It's perfectly possible (though rather silly) to write stateful components without state changes.

Collapse
 
adevnadia profile image
Nadia Makarevich

Good point :)