Performance React.PureComponent不';当组件有子组件时无法工作?
在React中使用PureComponent来提高渲染性能似乎是一种常见的技术。然而,当使用有子对象作为道具的PureComponent时,情况似乎并非如此Performance React.PureComponent不';当组件有子组件时无法工作?,performance,reactjs,components,react-dom,Performance,Reactjs,Components,React Dom,在React中使用PureComponent来提高渲染性能似乎是一种常见的技术。然而,当使用有子对象作为道具的PureComponent时,情况似乎并非如此 class App extends React.PureComponent { render() { console.log('re-render') return <div>{this.props.children}</div> } } const render = () => {
class App extends React.PureComponent {
render() {
console.log('re-render')
return <div>{this.props.children}</div>
}
}
const render = () => {
ReactDOM.render(
<App>
<div />
</App>,
document.getElementById('app')
)
setTimeout(render, 1000)
}
render()
类应用程序扩展了React.PureComponent{
render(){
console.log('re-render')
返回{this.props.children}
}
}
常量渲染=()=>{
ReactDOM.render(
,
document.getElementById('app')
)
设置超时(渲染,1000)
}
render()
结果是控制台每1s记录一次“重新渲染”。看来子组件(
)是上面应用程序组件的唯一道具,而且从未改变,为什么应用程序仍然被重新渲染
注意:如果有任何混淆,问题是相同的,既然道具似乎没有改变,为什么上面PureComponent的SCU(shouldComponentUpdate)钩子返回true 这里发生的事情是,您实际上正在调用ReactDOM.render()
,Page(或应用程序,我想您在这里有输入错误)组件将触发其render()
函数,而不管使用component
或PureComponent
PureComponent帮助减少不必要的渲染的方法是,当出现属性更改时,PureComponent将对这个.props
和nextrops
做一个粗略的比较,以确定这个PureComponent是否需要调用render()
我刚才给你举了个例子:
class App extends React.PureComponent {
state = {value: 0}
componentDidMount() {
setInterval(() => {
this.setState({value: Math.random()})
}, 1000)
}
render() {
return (
<div>
<PureChild value="fixed value"/>
<ImpureChild value="fixed value"/>
</div>
)
}
}
class PureChild extends React.PureComponent {
render() {
console.log('rendering PureChild')
return <div>{this.props.value}</div>
}
}
class ImpureChild extends React.Component {
render() {
console.log('rendering ImpureChild')
return <div>{this.props.value}</div>
}
}
类应用程序扩展了React.PureComponent{
状态={值:0}
componentDidMount(){
设置间隔(()=>{
this.setState({value:Math.random()})
}, 1000)
}
render(){
返回(
)
}
}
类PureChild扩展了React.PureComponent{
render(){
console.log('呈现PureChild')
返回{this.props.value}
}
}
类inpurechild扩展了React.Component{
render(){
console.log('rendering inpurechild')
返回{this.props.value}
}
}
请注意以下几点:
两个孩子都收到固定道具(“固定值”字符串)
每1秒,父级
会更改值
状态,从而重新渲染,导致其所有子级也重新渲染
但是由于
是一个PureComponent,它对它的旧道具和新道具做了一个粗略的比较,并注意到两个道具都是的“固定值”
,因此它不会触发渲染李>
如果运行此代码并打开控制台,则每1s只会看到“rendering inpurechild”,但“rendering PureChild”只会出现一次。现在根据ReactDOM
ReactDOM.render()
控制传递的容器节点的内容
在里面第一次调用时,将替换其中的任何现有DOM元素。
以后的调用使用React的DOM扩散算法进行高效更新
ReactDOM.render()
不修改容器节点(仅修改
容器的子容器)。可以插入一个
组件添加到现有DOM节点,而不覆盖现有DOM节点
孩子们
从第二次开始,ReactDOM只使用它在别处使用的扩散算法更新React组件,因此导致重新渲染的不是ReactDOM。您可以通过在应用程序组件中添加组件willmount
方法来验证这一点,并检查它是否只被调用一次
现在来看PureComponent。文件说,
React.PureComponent的
shouldComponentUpdate()
只是粗略地比较了对象。如果这些数据包含复杂的数据结构,则可能会因更深层次的差异而产生误报。仅当您希望有简单的道具和状态时才扩展PureComponent
所以这里有一个问题,PureComponent可能会返回假阴性,以获得更深层次的差异。因此,当您尝试将this.props.children
与nextrops.children
进行相等性比较时,您会发现它返回false
,因此会再次触发重新渲染
检查控制台日志(==)//false
在的每一次重新加载时,都是由React.createElement(div,null)
创建的,因此这个.props.children
将不同于nextrops.children
,尽管它们在中看起来相同
事实上,真正的问题是,props.children的引用(否则值为基元类型)在每次父级重新呈现和React.PureComponent时都会发生更改。PureComponent通过包含不变性的引用来比较props。根据React.PureComponent的文档
1) 。PureComponent实现shouldComponentUpdate()带有浅层道具和状态比较,将检查页面是否需要重新呈现
2) 。如果道具或状态中存在复杂对象,则PureComponent将给出假阳性结果,必须运行强制更新
3) 。父组件中的更改不会更新子组件,因此PureComponent的子组件也应该是PureComponent请问您为什么在render
内部调用render
?当您执行ReactDOM.render(..)
时,您已经呈现了应用程序,然后您再次递归调用它。是不是导致你的应用程序多次被重新下载?@margaretkru我故意触发rerender,让它测试上面的应用程序纯组件的SCU。添加注释:)请先查看详细答案!补充说明,我对纯组件部分很感兴趣,您是否介意对props.children的最后一部分进行详细说明,为什么这个.props与下一步会发生变化?补充说明,造成混淆是我的错,这可能不是我的问题,但感谢您的努力!
console.log(<div /> === <div />) // false