当Component有子节点时,React.PureComponent不起作用?

Xle*_*lee 8 performance components reactjs react-dom

使用PureComponent来改善React中的渲染性似乎是一种常见的技术.但是,使用具有子项作为道具的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()
Run Code Online (Sandbox Code Playgroud)

结果是控制台每1秒保持记录"重新渲染".似乎children(<div />)是上面App组件的唯一支柱并且永远不会改变,为什么App仍然会被重新渲染?

注意:如果有任何混淆,问题是相同的,为什么上面的PureComponent的SCU(shouldComponentUpdate)钩子返回true,因为没有道具似乎改变了?

Lir*_*Yeo 5

这里发生的是你实际上正在调用ReactDOM.render(),Page(或App,我认为你这里有一个拼写错误)组件会触发它的render()功能而不管使用ComponentPureComponent.

PureComponent可以帮助减少不必要的渲染的方式是当有一个prop更改时,PureComponent将进行浅层比较this.propsnextProps确定此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>
  }
}
Run Code Online (Sandbox Code Playgroud)

注意以下几点:

  1. 两个孩子都收到固定的道具("固定值"字符串)
  2. 每1秒,父<App />更改value状态,因此它重新呈现,导致其所有子项也重新呈现.
  3. 由于它<PureChild />是一个PureComponent,它对旧的道具和传入的新道具进行浅层比较,并且通知两个道具都是"fixed value",因此它不会触发渲染!

如果你运行这个代码并打开控制台,你会看到每1秒'渲染一次ImpureChild',但'渲染PureChild'只会出现一次.


Xle*_*lee 5

 console.log(<div /> === <div />) // false
Run Code Online (Sandbox Code Playgroud)

每次重绘时<App />,都会创建一个新的 React ElementReact.createElement(div, null),因此与JSX中的外观相同。this.props.childrennextProps.children

实际上,真正的问题是props.children每次父级重新渲染并且React.PureComponent通过引用包含不变性来比较props时,引用的引用(否则为值,如果是原始类型)就会发生变化。