【问题标题】:Does object creation in the render method break 'React.PureComponent' and render checking in 'shouldComponentUpdate'?渲染方法中的对象创建是否会破坏“React.PureComponent”并在“shouldComponentUpdate”中进行渲染检查?
【发布时间】:2019-07-13 12:00:03
【问题描述】:

tl;dr:当您在 render 方法中创建对象/组件以作为 props/children 传递给渲染组件时,它是否无法通过 shouldComponentUpdate 中的 React.PureComponent 和 prop 检查?

我经常看到类似的模式:

  render() {
    const commentTrigger = <Button>Comment</Button>;
    const deleteTrigger = <Button>Delete Thread</Button>;
    const someComponentProps = { 
      prop1: this.getProp1()
      prop2: this.props.prop2
    }

    return (
      <div>
        <SomeModal trigger={commentTrigger} />
        <SomeOtherModal trigger={deleteTrigger} />
        <SomeComponent {...someComponentProps}
      </div>
    )
  }

这是否会使 SomeComponent 中的 .PureComponent 检查或 shouldComponentUpdate 检查失败,因为 someComponentProps 每次都是不同的对象,特别是(假设 this.getProp1() 是新创建的对象)单独 prop1 会导致这些测试失败并且最终重新渲染组件?如果 this.getProp1() 只是一个数字呢?

否则,是否有充分的理由不以这种方式编写 React 组件? 提前感谢您的帮助。如果我应该改写问题或澄清任何事情,请告诉我。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    PureComponent 会对它的 props 做一个浅的比较,基本上使用Object.is() 比较。在对象的情况下,这意味着只有当它是同一个对象时才会通过,而不是当它是具有所有相同属性的不同对象时。

    因此,您的前两个示例(commentTrigger 和 deleteTrigger)将遇到此问题。每次渲染时它们都是全新的对象,与之前的对象无关,因此不会传递三等号。

    在您的第三个示例(传播 someComponentProps)中, someComponentProps 是否是新对象没有区别。通过传播它,您传递了一系列单独的道具,从prop1={someComponentProps.prop1} 开始并贯穿对象的其余属性。当您不知道有多少道具时,这是一种方便的语法。如果 SomeComponent 是纯组件,它会检查 prop1 是否改变,prop2 是否改变,甚至不知道 someComponentProps 是否存在。

    【讨论】:

    • 感谢您的帮助,这更有意义。对于前两个示例,是否创建单独的功能组件并直接将它们作为道具插入,以便它们始终相同?
    • 有几个选项供您使用。我不知道该推荐什么,因为我不知道道具将用于什么。是的,一种选择是让 SomeModal 期望您传递一个组件。但是你可能需要更多的控制,在这种情况下你可以考虑做一个渲染道具reactjs.org/docs/render-props.html)。然后,您将一个函数传递给 SomeModal,并让该函数成为您的主组件上的一个方法(即,它不是在渲染中创建的)。第三种选择是编写一个自定义的 shouldComponentUpdate ,它会忽略 trigger 属性,所以如果你改变它也没关系。
    【解决方案2】:

    PureComponent 对 props 对象进行浅层相等检查。如果下一个prop1 值(使用this.getProp1() 创建)是=== 等于上一个值,prop2 也是如此,SomeComponent 将不会被更新。

    即使 props 不等于 ===,也可以在 shouldComponentUpdate 中实现自定义检查,例如深度相等性检查。

    【讨论】:

      猜你喜欢
      • 2023-03-14
      • 1970-01-01
      • 2018-02-13
      • 2022-10-04
      • 2021-07-12
      • 2019-01-17
      • 2019-08-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多