我的理解是PureComponent利用shouldComponentUpdate()
并对状态和道具进行浅层比较,但我创建了一个与我预期不同的小例子。
示例应用程序显示人员列表。每个列表项都可以更改其名称。尝试一下并检查代码here。
在父组件中,我有一个如下所示的方法:
updateName(id, newName) {
const { people } = this.state
const idx = people.findIndex(person => person.id === id)
people[idx].name = newName
this.setState({ people })
}
我传回setState
的对象与前一个对象具有相同的引用。在这种情况下,如果该组件进行浅层比较,该组件是否应该不更新?
其次,另一部分不清楚,我将子组件Person
从PureComponent更改为Component,我仍然只获得了更新重新渲染的子项的好处(I& #39;如果要检查那个,则在每个子渲染上执行控制台登录。很明显,这是React在内部做的事情,决定孩子是否应该更新,但我认为如果组件重新渲染,它将重新渲染所有内容。
答案 0 :(得分:2)
如果该组件进行浅层比较,该组件是否不应更新?
是的。而且它没有更新。您可以看到在初始渲染后不会再次调用App
组件的render()
方法。这意味着浅层比较正如您所期望的那样工作并且组件(正确地)不更新。
我相信那些让你失望的部分是Person.prototype.handleSubmit()
中的这一行:
this.setState({ value: '' })
从oldState.value !== newState.value
开始,无论Person
是否为Person
,都会触发修改后的PureComponent
组件的重新呈现。
如果你拿出这一行,你会看到没有任何更新(你期望的行为)。
显然,这是React在内部做的事情,以决定孩子是否应该更新。
不,孩子正在设定自己的状态。这里的亲子关系无关紧要。 React将直接更新孩子。
将来你应该尝试隔离你的测试。这种混乱的原因是因为你依靠render()
方法来确定一个孩子是否收到了新的道具。但是,当孩子收到新道具并且孩子设置新状态时,会调用render()
方法。
对这种情况的一个更好的测试是检查componentWillReceiveProps()
是否被调用,从而从图片中删除state
:
componentWillReceiveProps(newProps) {
console.log('receiving props', newProps)
}
如果将其插入Person
组件,您将看到它未被调用。正如你所期待的那样。
简而言之,React.PureComponent
完全按照您的想法运作。