简体   繁体   中英

In React, when a parent component re-renders, isn't it true that the children with unchanged props should not need to re-render?

I think the fact is that, when a parent component re-renders in React, in general, all the children components re-render as well .

I did one experiment to confirm:

https://codesandbox.io/s/currying-pine-r16rzi

  return (
    <div>
      <div>Time now is {timeNow.toLocaleTimeString()}</div>
      <TheTimeNow /><TheTimeNow />
    </div>
  );

This parent component re-renders, and <TheTimeNow /> has no change in props value (it has none), but it re-renders anyway and shows the updated time.

I think it is not the same to say, that React actually change the DOM, as I think the mechanism is that React use the previous virtual DOM to compare with the new virtual DOM, and update only the minimal actual DOM node as on document.documentElement as needed.

This can be seen if you use Google Chrome and do Inspect Element on the time statement: only the time portion changes and the other English words stay the same. Compare to this where all the nodes changes if it is plain JavaScript: https://jsfiddle.net/8sj2ugae/1/ when you do Inspect Element.

However, can't we argue that, if a child is <Foo /> and since there is no props passed to it, then <Foo /> really should not have changed, and it is wasteful to call Foo() ? (if Foo is a functional component, or call the render() method if it is a class component.)

Now since all children re-renders, that means all their children also get re-rendered. Repeat this rule recursively, that would mean the whole subtree gets re-rendered.

My question is: is it true that they should not need to re-render if their props didn't change, or are there other factors that make them needing a re-render really?

The answer is yes, there is no need to rerender. But in order to know this we need to compare a new props with a previous props. And this operation is not free.

Also if we do a shallow comparison we are increasing the probability of bugs. Someone might be expecting rerender after a deep props update.

Should React.memo be the deault behaviour? Will it improve the performance in most cases? We don't know. There is no evidence for that. More on this in Mark Erikson's post .

Here is a great article by Dan Abramov: Before You memo() . I consider two points regarding your question:

  1. In the future compiler might decide when to memoize a component.

  2. Component rendering doesn't mean that all it's children will be rerendered.

Here is an example:

const ParentComponent = ({ children }) => {
  const [state, setState] = useState(0);
  return <div>{children}</div>
}

If we update the state children will not be rerendered. React just uses a previous value. Here is an article by Kent C. Dobbs about this optimization technique.

One last thing. React.memo and useMemo are different. The first one is for component memoization and the second one is a hook for expensive calculations. There are also shouldComponentUpdate for class components and PureComponent which compare not only props but also a state.

Hopefully the answer and links will shed some light on this topic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM