Performance React.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 = () => {

在React中使用PureComponent来提高渲染性能似乎是一种常见的技术。然而,当使用有子对象作为道具的PureComponent时,情况似乎并非如此

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