繁体   English   中英

React组件是否会深入比较道具以检查是否需要重新渲染?

[英]Does a React component deeply compare props to check if rerender is needed?

我想知道在尝试确定是否需要重新渲染时,扩展React.Component的React组件React.Component深深地比较对象。

例如,给定

const Foo = ({ bar }) => {
  return <div>{bar.baz}</div>
}

class App extends React.Component {
  constructor() {
    super()
    this.state = { bar: { baz: 1} }
  }

  render() {
    return <Foo bar={this.state.bar} />
  }
}

如果内部App ,状态bar变为{baz: 2}确实<Foo />深深比较以前的支柱bar和新接收到的支柱?

顺便提一下, PureComponent的文档

扩展PureComponent ...或者,考虑使用不可变对象来促进嵌套数据的快速比较。

但是没有详细介绍。 有任何想法吗?

除非您自己实现了shouldComponentUpdate生命周期方法,否则扩展React.Component的组件React.Component重新渲染周期之前不会比较道具,它会比较前一个和当前的Virtual DOM来决定重新渲染的内容。

使用React.PureComponent扩展的组件也不会将prevProps和prevState的状态与prevState进行深度比较,但是如果需要重新渲染则需要执行浅比较来决定是否需要重新渲染。

对于v16.6.0以后的Functional component ,React引入了一个高阶函数React.memo ,可用于使函数组件表现为React.PureComponent

根据文件

React.memo是一个更高阶的组件。 它与React.PureComponent类似,但是对于函数组件而不是类。

它可以像

 const MyComponent = React.memo(function MyComponent(props) { /* render using props */ }); 

如果你的函数组件在给定相同的道具的情况下呈现相同的结果,你可以在调用React.memo时将其包装起来,以便在某些情况下通过记忆结果来提高性能。 这意味着React将跳过渲染组件,并重用最后渲染的结果。

默认情况下,它只会shallowly compare complex objects props对象中的shallowly compare complex objects对象。 如果要控制比较,还可以提供自定义比较函数作为第二个参数。

'Extend PureComponent'被引用脱离了背景。 文档说的相反,

只有在您希望拥有简单的道具和状态时才能扩展PureComponent

因为

React.PureComponent的shouldComponentUpdate()只是浅浅地比较对象。 如果这些包含复杂的数据结构,则可能会产生更深层次差异的假阴性。

React组件不会比较props,除非它们实现了shouldComponentUpdate ,就像PureComponent一样。 可以使用完全相同的prop( ===相等)重新渲染组件。

如果状态发生变异但未被强制更新(这是反模式),则不会重新渲染子项。

如果状态发生变异并被强制更新(这是反模式),则会重新呈现子项:

class App extends React.Component {
  componentDidMount() {
     this.state.bar.baz = 2;
     this.setState(state);
  }
  ...    
}

为了限制对深度更改的道具的更新, Foo应该通过深度比较实现shouldComponentUpdate ,例如Lodash isEqual

class Foo extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    return !_.isEqual(this.props, nextProps) || this.state !== nextState;
  }
  ...
}

由于深度比较可能代价高昂,因此应运行性能测试以确定其是否提供性能改进。

React非常欢迎不可变状态和道具,因为它们可以避免这个问题。 如果一个对象以某种方式改变,它应该被另一个对象替换,即状态更新应该导致新的statestate.bar对象:

class App extends React.Component {
  componentDidMount() {
    this.setState(({ bar })=> ({
      bar: { ...bar, baz: 2 }
    });
  }
  ...    
}

在这种情况下, Foo需要浅浅地比较它作为prop获得的bar对象,因此它可以是PureComponentReact.memo (另一个答案解释)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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