[英]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非常欢迎不可变状态和道具,因为它们可以避免这个问题。 如果一个对象以某种方式改变,它应该被另一个对象替换,即状态更新应该导致新的state
和state.bar
对象:
class App extends React.Component {
componentDidMount() {
this.setState(({ bar })=> ({
bar: { ...bar, baz: 2 }
});
}
...
}
在这种情况下, Foo
需要浅浅地比较它作为prop获得的bar
对象,因此它可以是PureComponent
或React.memo
(另一个答案解释)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.