在React中,当父组件重新渲染时,是否props未更改的子组件不需要重新渲染?

nop*_*ole 8 rerender reactjs

我认为事实是,当父组件在 React 中重新渲染时,通常所有子组件也会重新渲染

我做了一个实验来证实:

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

  return (
    <div>
      <div>Time now is {timeNow.toLocaleTimeString()}</div>
      <TheTimeNow /><TheTimeNow />
    </div>
  );
Run Code Online (Sandbox Code Playgroud)

该父组件重新渲染,并且<TheTimeNow />props 值没有变化(它没有),但它仍然重新渲染并显示更新时间。

我认为React实际上改变了DOM是不一样的,因为我认为其机制是React使用以前的虚拟DOM与新的虚拟DOM进行比较,并根据需要仅更新最小的实际DOM节点document.documentElement

如果您使用 Google Chrome 并在时间语句上执行 Inspect Element,就可以看到这一点:只有时间部分发生变化,其他英文单词保持不变。与此相比,如果是纯 JavaScript,则所有节点都会发生变化: https: //jsfiddle.net/8sj2ugae/1/,当您执行 Inspect Element 时。

然而,我们不能说,如果一个孩子是<Foo />并且由于没有传递给它的道具,那么<Foo />真的不应该改变,并且调用是浪费的Foo()?(如果Foo是函数组件,或者render()如果是类组件则调用该方法。)

现在,由于所有子项都会重新渲染,这意味着它们的所有子项也会重新渲染。递归地重复这个规则,这意味着整个子树被重新渲染。

我的问题是:如果他们的道具没有改变,他们是否真的不需要重新渲染,或者是否有其他因素使他们真的需要重新渲染?

Iva*_*lin 5

答案是肯定的,不需要重新渲染。但为了了解这一点,我们需要将新道具与以前的道具进行比较。而且这个操作并不是免费的。

此外,如果我们进行浅层比较,就会增加出现错误的可能性。有人可能期望在深度 props 更新后重新渲染。

应该React.memo是默认行为吗?在大多数情况下它会提高性能吗?我们不知道。没有证据证明这一点。马克·埃里克森 (Mark Erikson) 的帖子对此有更多介绍。

这是 Dan Abramov 写的一篇很棒的文章:Before You memo()。对于你的问题我考虑两点:

  1. 将来编译器可能会决定何时记忆组件。

  2. 组件渲染并不意味着它的所有子组件都会被重新渲染。

这是一个例子:

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

如果我们更新状态,子项将不会被重新渲染。React 仅使用先前的值。这是Kent C. Dobbs 撰写的关于这种优化技术的文章。

最后一件事。React.memo并且useMemo是不同的。第一个用于组件记忆,第二个是用于昂贵计算的挂钩。还有shouldComponentUpdate类组件,PureComponent它们不仅比较道具,还比较状态。

希望答案和链接能够对这个主题有所启发。