【问题标题】:React.PureComponent renders all the items in a list componentReact.PureComponent 渲染列表组件中的所有项目
【发布时间】:2019-11-21 17:05:56
【问题描述】:

我们使用 ReactJS 创建了一个可重用的列表组件。然而,由于性能问题,我们决定实现 - shouldComponentUpdate 方法,条件是我的列表组件何时呈现

public shouldComponentUpdate(nextProps: TreeItemInternalProps, nextState: {}): boolean {
  if (this.props.treeObject.selected !== nextProps.treeObject.selected) {
    return true;
  }
  if (this.props.treeObject.expanded !== nextProps.treeObject.expanded) {
      return true;
    }
  return false;
}

意思是,我只想在列表项复选框的值发生变化时渲染我的组件。

假设由于某种原因,我不能再这样做了。现在,我的替代方案是使用 PureComponent 进行浅比较。因此,它应该只呈现更改的列表项。但是,即使在使用 PureComponent 之后使用,整个组件也会被渲染。

要正确解释该场景,请参阅以下屏幕截图 -

  1. 不使用 PureComponent / 在 shouldComponentUpdate 中使用条件检查

这里可以看到“组件被渲染”的日志只调用了一次,意思是只针对我在prop中做的改变(这个需求是一样的,我想用PureComponent来实现)


  1. 使用 PureComponent

在这里,您可以看到日志“组件已渲染”被调用了 3 次,即使我只更改了第一个列表项的 props。这是使用 PureComponent

【问题讨论】:

  • PureComponent 对您的道具进行shallow 检查,以进行深入比较,您可能需要拥有生命周期。阅读:medium.com/@baphemot/…
  • 你能分享一些你的代码吗?
  • 如果我理解正确的话,PureComponent 只会在 props 或 state 发生任何变化时渲染。然而,只有 React.Component 每秒渲染一次。 @Nicolae Maties
  • 是的,这是真的。您正在更改 parent 或 state 中的道具。您需要共享组件及其父组件的代码,以便我们为您提供帮助。或者创建一个代码框以在没有您的确切代码的情况下重现问题。
  • @Domino987 给我一些时间,我将返回代码或者如果我能够设置沙箱

标签: javascript reactjs typescript


【解决方案1】:

PureComponent 始终为您呈现,因为您的 PropsState 很可能包含在父组件重新呈现期间在父组件中创建的任何对象或数组。

正如其他人所说,它对重新渲染进行了浅层比较(意味着对象引用不会等于新对象引用,即使它们是 DEEP 相等),所以父组件是它的瓶颈PureComponent 子,因为每次重新渲染都会重新创建一个全新的对象引用

如果您真的想使用 PureComponent,则必须将组件中的所有其他道具简化为在每次重新渲染父组件时都不会获得新引用的基元或对象/数组

问题示例:

class Todo extends PureComponent {
  render() {
    return <div>this.props.foo</div>;
  }
}

class MyTodoList extends Component {
 render () {
   const fooBar = {foo: 'bar'}
   return <Todo fooBar={fooBar} />
  }
}

修复示例:

class Todo extends PureComponent {
  render() {
    return <div>this.props.foo</div>;
  }
}

class MyTodoList extends Component {
 render () {
   return <Todo fooBar={props.fooBar} />
  }
}

您想要做的最好的事情可能是将对象创建尽可能提高到不会重新渲染此类更改的组件,或者将每个单独的道具简化为非对象。

【讨论】:

    【解决方案2】:

    React.PureComponent 对它们的 props 和 state 进行浅层比较。 因此更改 state 或 props 的 object 属性不会重新渲染组件。 只有当利益的状态或道具发生变化时,我们才需要重建状态或道具。 例如,我们可以编写如下代码,仅在设置了 forceRender 标志时重新渲染。

    class ShalloWCompareComponent extends React.PureComponent {
      constructor() {
        super();
        this.state = {
          userArray: [1, 2, 3, 4, 5]
        }
      }
    
      update() {
        const { forceRender } = this.props;
        const { userArray } = this.state;
        if (forceRender) {
          this.setState({
            userArray: [...userArray, 6]
          });
        } else {
          this.setState({
            userArray: userArray.push(6)
          });
        }
      }
    
      render() {
        return <b>Array Length is: {this.state.userArray.length}</b>
      }
    }
    

    如果这个组件接收到 forceRender={false} 的 props,由于 React.PureComponent 的浅层比较,调用 update() 不会重新渲染组件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-14
      • 1970-01-01
      • 2019-06-05
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 2018-01-18
      相关资源
      最近更新 更多