简体   繁体   English

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

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

I would like to know if a React component extending React.Component deeply compares an object when trying to decide if it needs to rerender. 我想知道在尝试确定是否需要重新渲染时,扩展React.Component的React组件React.Component深深地比较对象。

For instance, given 例如,给定

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} />
  }
}

If inside App , the state bar changes to {baz: 2} , does <Foo /> deeply compare the previous prop bar and the newly received prop? 如果内部App ,状态bar变为{baz: 2}确实<Foo />深深比较以前的支柱bar和新接收到的支柱?

Incidentally, the docs for PureComponent says 顺便提一下, PureComponent的文档

Extend PureComponent ... Or, consider using immutable objects to facilitate fast comparisons of nested data. 扩展PureComponent ...或者,考虑使用不可变对象来促进嵌套数据的快速比较。

But does not go into much more details. 但是没有详细介绍。 Any ideas? 有任何想法吗?

Unless you implement a shouldComponentUpdate lifecycle method yourself, a component extending React.Component won't compare the props before going through a re-render cycle where it compares the previous and current Virtual DOM to decide what to re-render 除非您自己实现了shouldComponentUpdate生命周期方法,否则扩展React.Component的组件React.Component重新渲染周期之前不会比较道具,它会比较前一个和当前的Virtual DOM来决定重新渲染的内容。

Also a component extended using React.PureComponent doesn't deeply compare props with prevProps and state with prevState but performs shallow comparison to decide, if at all a re-render is needed or not. 使用React.PureComponent扩展的组件也不会将prevProps和prevState的状态与prevState进行深度比较,但是如果需要重新渲染则需要执行浅比较来决定是否需要重新渲染。

For a Functional component from v16.6.0 onwards, React has introduced a Higher Order Function, React.memo which can be used to make a functional component behave as a React.PureComponent 对于v16.6.0以后的Functional component ,React引入了一个高阶函数React.memo ,可用于使函数组件表现为React.PureComponent

According to the docs : 根据文件

React.memo is a higher order component. React.memo是一个更高阶的组件。 It's similar to React.PureComponent but for function components instead of classes. 它与React.PureComponent类似,但是对于函数组件而不是类。

It can be used like 它可以像

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

If your function component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result. 如果你的函数组件在给定相同的道具的情况下呈现相同的结果,你可以在调用React.memo时将其包装起来,以便在某些情况下通过记忆结果来提高性能。 This means that React will skip rendering the component, and reuse the last rendered result. 这意味着React将跳过渲染组件,并重用最后渲染的结果。

By default it will only shallowly compare complex objects in the props object. 默认情况下,它只会shallowly compare complex objects props对象中的shallowly compare complex objects对象。 If you want control over the comparison, you can also provide a custom comparison function as the second argument. 如果要控制比较,还可以提供自定义比较函数作为第二个参数。

'Extend PureComponent' was quoted out of context. 'Extend PureComponent'被引用脱离了背景。 The documentation says the opposite, 文档说的相反,

Only extend PureComponent when you expect to have simple props and state 只有在您希望拥有简单的道具和状态时才能扩展PureComponent

Because 因为

React.PureComponent's shouldComponentUpdate() only shallowly compares the objects. React.PureComponent的shouldComponentUpdate()只是浅浅地比较对象。 If these contain complex data structures, it may produce false-negatives for deeper differences. 如果这些包含复杂的数据结构,则可能会产生更深层次差异的假阴性。

React components don't compare props, unless they implement shouldComponentUpdate , like PureComponent . React组件不会比较props,除非它们实现了shouldComponentUpdate ,就像PureComponent一样。 A component can be re-rendered with exactly same prop ( === equal). 可以使用完全相同的prop( ===相等)重新渲染组件。

If the state is mutated but isn't forced to update (this is an antipattern), children won't be re-rendered. 如果状态发生变异但未被强制更新(这是反模式),则不会重新渲染子项。

If the state is mutated and forced to update (this is an antipattern), children are re-rendered: 如果状态发生变异并被强制更新(这是反模式),则会重新呈现子项:

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

In order to limit updates to deeply changed props, Foo should implement shouldComponentUpdate with deep comparison, eg Lodash isEqual : 为了限制对深度更改的道具的更新, Foo应该通过深度比较实现shouldComponentUpdate ,例如Lodash isEqual

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

Since deep comparison may be costly, performance tests should be run to determine whether it provides performance improvements. 由于深度比较可能代价高昂,因此应运行性能测试以确定其是否提供性能改进。

Immutable state and props are highly welcome in React because they allow to avoid this problem. React非常欢迎不可变状态和道具,因为它们可以避免这个问题。 If an object changes in some way, it should be replaced with another object, ie state update should result in new state and state.bar objects: 如果一个对象以某种方式改变,它应该被另一个对象替换,即状态更新应该导致新的statestate.bar对象:

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

In this case Foo needs to shallowly compare bar object it receives as a prop, so it can be PureComponent , or React.memo (as another answer explains). 在这种情况下, Foo需要浅浅地比较它作为prop获得的bar对象,因此它可以是PureComponentReact.memo (另一个答案解释)。

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

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