14

When will a React component using hooks re-render?

Let's assume the component:

  • Manages state with useState
  • Receives props from its parent

Will a re-render happen directly after the following events, and only at those points in time?

  • Component receives new props
  • state is updated

Related Question

Let's assume the component has several useState expressions and a user interaction causes multiple states to update.

Will the component re-render multiple times, once per state value that changed, or will it batch these related changes into one single re-render?

Magnus
  • 6,791
  • 8
  • 53
  • 84

2 Answers2

15

A component will re-render in the following cases considering it doesn't implement shouldComponentUpdate for class component, or is using React.memo for function

  • Component receives new props
  • state is updated
  • Context value is updated(if the component listenes to context change using useContext)
  • Parent component re-renders due to any of the above reasons

Let's assume the component has several useState expressions and a user interaction causes multiple states to update.

Will the component re-render multiple times, once per state value that changed, or will it batch these related changes into one single re-render?

useState doesn't merge the updated values with previous ones but performs batching like setState and hence if multiple state updates are done together, one render take place.

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • Thanks! What does multiple states updated together mean? – Magnus Mar 11 '19 at 18:51
  • What I meant is that if you have two state variables `countA` and `countB` and you update both of them one after other using their respective state setters, they are batched – Shubham Khatri Mar 11 '19 at 18:52
  • Sorry to dig in, but do you mean within one tick of the JS event loop? I.e. in what case would they *not* be batched? – Magnus Mar 11 '19 at 18:54
  • 1
    There is a small time interval within which if multiple calls to useState setter occur their updates will be batched. However if setter calls occur with a mininum time interval greated than the batching interval then those updates will not be batched – Shubham Khatri Mar 12 '19 at 05:36
  • "Component receives new props" shouldn't be in this list. It doesn't rerender per se. See https://stackoverflow.com/a/38893045/3032209 – Yair Kukielka Nov 18 '21 at 17:12
5

Found this nice article on this topic. I'll add the summary in case someone needs a quick read.

What causes a render in react?

State modification

Component re-renders when its state is manipulated, simple as that. So, when you modify the state of your component it tends to re-renders with the new state value.

Passing Props

If the parent component has triggered a rerender all the child component will rerender too, generally you would only want the specific child components to rerender only if the component is consuming some props or the passed props are modified but that isn’t the case, it does not matter if the props are consumed, modified or not, the child components will re-render if the parent component has triggered a render.

Using the Context API

When modifying the state which is also the value passed to the context, the whole child components tree would get rerendered. Again doesn’t matter if the child component is consuming the context data or not, it will still rerender. The rerenders depend on the value passed to the provider but still, all the whole components tree would get rerendered.

Passing down references

In case of an object, array and, function comparison is based on references i.e. the exact memory location so, their comparison even though they seem equal yields false, in React Object.is method is used to compare the different values.

Example:

{}==={}             //false
[]===[]             //false
{a: 5}==={a: 5}     //false
[1,2,3]===[1,2,3]   //false

(when comparing the previous state to the new state, it returns false because they do not have the same reference. Only the value is the same)

Rukshan Jayasekara
  • 1,945
  • 1
  • 6
  • 26