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:
- Part 1: what is re-render in React?
- Part 2: when React component re-renders itself?
- Part 3: preventing re-renders with composition
- Part 4: preventing re-renders with React.memo
- Part 5: improving re-renders performance with useMemo/useCallback
- Part 6: improving re-renders performance of lists
- Part 7: preventing re-renders caused by Context
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.
🧐 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).
🧐 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).
🧐 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.
⛔️ 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.
Only when memoization techniques are used (React.memo
, useMemo
), then props change becomes important.
See the rest of the guide here:
- Part 1: what is re-render in React?
- Part 2: when React component re-renders itself?
- Part 3: preventing re-renders with composition
- Part 4: preventing re-renders with React.memo
- Part 5: improving re-renders performance with useMemo/useCallback
- Part 6: improving re-renders performance of lists
- Part 7: preventing re-renders caused by Context
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.
Top comments (8)
Very insightful.
Thanks a lot
Thanks for sharing this solid article, keep going
This was amazing, thanks!
Minor nitpick: The mere existence of
useState
is not a state change. It's thesetState
call that actually changes the state. It's perfectly possible (though rather silly) to write stateful components without state changes.Good point :)
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.
Excellent article especially those codesandbox links to play around for getting even clearer picture.
If I summarize the difference between context and hook changes:
Again, it's a excellent article which explains things without unnecessarily trying to impress the readers.
very nice. i am still very weak at context hook, other than the context part, it was very clean article