我想知道扩展React.Component
的React组件在尝试确定是否需要重新渲染时是否深深地比较了该对象。
例如,给定
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
与新接收的道具进行深度比较?>
偶然地,the docs for PureComponent说
扩展PureComponent ...或者,考虑使用不可变对象来促进嵌套数据的快速比较。
但是没有涉及更多细节。有什么想法吗?
答案 0 :(得分:5)
除非您自己实现shouldComponentUpdate
生命周期方法,否则扩展 React.Component
的组件将不会在通过比较之前与之前的渲染周期之前比较道具。和当前的虚拟DOM决定要重新渲染的内容
使用 React.PureComponent
扩展的组件不会将props与prevProps进行深度比较,而state与prevState进行深度比较,而是进行浅层比较以确定是否需要重新渲染
对于 v16.6.0 起的 Functional component
,React引入了高阶函数React.memo
,可用于制作一个功能组件的行为类似于React.PureComponent
根据 docs :
React.memo
是一个高阶组件。这类似于React.PureComponent
,但用于功能组件而不是类。可以像
一样使用const MyComponent = React.memo(function MyComponent(props) { /* render using props */ });
如果函数组件在相同条件下呈现相同结果 道具,您可以将其包装在对React.memo的调用中以提高性能 在某些情况下,通过记忆结果。这意味着React将跳过 渲染组件,然后重用最后渲染的结果。
默认情况下,道具只会
shallowly compare complex objects
宾语。如果您想控制比较,还可以提供 自定义比较函数作为第二个参数。
答案 1 :(得分:0)
'Extend PureComponent'被引用在上下文之外。文档说的相反,
仅当您希望具有简单的道具和状态时才扩展PureComponent
因为
React.PureComponent的shouldComponentUpdate()仅浅浅地比较对象。如果这些数据包含复杂的数据结构,则可能会产生假阴性,从而产生更大的差异。
反应组件不会比较道具,除非它们实现shouldComponentUpdate
,例如PureComponent
。可以使用完全相同的道具({===
相等)重新渲染组件。
如果状态发生了变化但没有被强制更新(这是一种反模式),则不会重新渲染子级。
如果状态发生变化并被强制更新(这是一种反模式),则会重新渲染子级:
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
需要浅比较它作为道具接收的bar
对象,因此它可以是PureComponent
或React.memo
(如另一个答案所解释)。