【问题标题】:React.PureComponent not implementing shouldComponentUpdateReact.PureComponent 没有实现 shouldComponentUpdate
【发布时间】:2017-06-14 06:49:26
【问题描述】:

我可能遗漏了一些东西,但我有一个像这样的组件

export default MyComponent extends React.PureComponent {
    // ...
}

当 MyComponent 是另一个组件渲染方法的一部分时,MyComponent 会在每次父渲染时重新渲染,即使 props/state 未更改。所以似乎从React.Component 更改为React.PureComponent 并没有使组件“纯”。

我尝试添加

console.info(this.shouldComponentUpdate)

在组件方法之一中,它说它是未定义的。 React.PureComponent 不应该添加一个浅比较的shouldComponentUpdate 方法吗?

现在 React 15.5.415.6.0

已经发生了这种情况

【问题讨论】:

    标签: reactjs ecmascript-6


    【解决方案1】:

    PureComponent 不直接声明shouldComponentUpdate。您无法使用this.shouldComponentUpdate 访问它。在 React 源代码中有一个 shouldUpdate 变量:

    (以下源代码已简化)

    // default is true
    var shouldUpdate = true;
    
    if (inst.shouldComponentUpdate) {
      shouldUpdate = inst.shouldComponentUpdate(
        nextProps,
        nextState,
        nextContext,
      );
    } else {
      // if it's a PureComponent
      if (this._compositeType === ReactCompositeComponentTypes.PureClass) {
        shouldUpdate =
          !shallowEqual(prevProps, nextProps) ||
          !shallowEqual(inst.state, nextState);
      }
    }
    
    // ...
    
    if (shouldUpdate) {
      // re-render ..
    }
    

    因为它只是浅相等,所以下面的代码返回 false,你会得到一个重新渲染:

    const propA = { foo: 'bar' }
    const nextPropA = { foo: 'bar' }
    
    shallowEqual(propA, nextPropA) // false
    

    因此请谨慎使用对象和数组。要证明 PureComponent 有效,请参见此示例 (v15.6):https://codepen.io/CodinCat/pen/eRdzXM?editors=1010

    点击按钮不会触发Foo的渲染:

    这是 PureComponent 可能不适合您的另一个示例:https://codepen.io/CodinCat/pen/QgKKLg?editors=1010

    唯一的区别是<Foo someProp={{ foo: 'bar' }} />

    因为{ foo: 'bar' } !== { foo: 'bar' },React 每次都会重新渲染。所以直接在 props 中写 inline 对象和数组并不是一个好习惯。一个常见的错误是编写内联样式:

    <Foo style={{ color: 'pink' }} />
    

    在这种情况下,Foo 将始终重新渲染,即使它是 PureComponent。如果您遇到此问题,您可以简单地提取对象并将其存储在某处,例如:

    const someProp = { foo: 'bar' }
    
    <Foo someProp={someProp} />
    

    someProp === someProp 开始,PureComponent 就可以工作了。

    【讨论】:

    • 看起来这是由作为道具传递的对象引起的。我理解比较问题,但觉得离开 obj/arr 道具并不是最好的解决方案。这是因为应用程序中的数据结构与可重用组件相结合通常会导致传递实体列表,然后将一个实体发送到子组件进行渲染,通常与其他一些道具一起。如果我将所有实体数据道具与其他(如行为)道具混合在一起,道具定义就会变得一团糟。我想这意味着我需要创建自己的 shouldComponentUpdate,所以我不能使用 React.PureComponent。
    • 我的意思是内联编写对象和数组。更新了答案以使其更清晰
    • 尽量不要使用 &lt;Foo style={{ color: 'pink' }} /&gt; 这样的东西,那么 PureComponent 应该可以工作
    • @henit 不一定。您还可以将所有状态提取到顶部并使用不可变(例如 redux 架构)。这将使纯渲染的整个概念更容易实现。
    • 嗯,现在我有一个带有一组道具的对象(例如 { id: 1234, name: 'My name' })。然后,当一个组件在其 props 中使用该对象渲染 MyComponent 时,使用同一对象的不可变副本但具有完全相同的内容的重新渲染会触发 PureComponent 上的重新渲染。有什么办法可以避免这种情况而不需要自己制作 shouldComponentUpdate 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 2019-03-10
    • 2017-01-18
    • 2023-03-14
    • 1970-01-01
    • 2017-05-11
    • 1970-01-01
    相关资源
    最近更新 更多