【问题标题】:React - Would'nt React.PureComponent or shouldComponentUpdate always result in not re -rendering if dealing with object?React - 如果处理对象,React.PureComponent 或 shouldComponentUpdate 是否总是导致不重新渲染?
【发布时间】:2023-03-14 22:03:01
【问题描述】:

我发现了很多关于 PureComponents 浅层比较的帖子,但想知道以下几点:

如果 React.PureComponent 或 shouldComponentUpdate 仅进行浅比较 - 这是否意味着如果我通过道具传递一个对象或将我的状态与 nextState (这是一个对象)进行比较,即使该对象的属性也总是会导致 false已经改变(因为它仍然指向同一个对象并且没有进行属性比较),因此,我的组件不会重新渲染?

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    是的,由于对象相同,您可能会遇到未调用渲染的情况。甚至官方文档也建议不要将对象值传递给PureComponent

    仅当您希望拥有简单的道具和状态时扩展 PureComponent,或者当您知道深层数据结构已更改时使用 forceUpdate()。或者,考虑使用不可变对象来促进嵌套数据的快速比较。

    但是一旦你避免改变这个在父组件中传递给props的对象,这将起作用。

    如果你像 redux 的 reducers 那样做(一旦内部发生任何变化就返回新对象)你会没事的。

    但同样,因为它需要任何人的额外关注,所以更安全的是避免传递对象并爆炸独立传递的原始值列表中的所有数据

    [UPD] 让我们来看几个父组件代码的例子:

    这里 MyPure 将始终重新渲染,因为每次传递的对象不同:

    render() {
        let childData = {....}; 
        ....
        return (
        .... 
            <MyPure data={childData} />
    

    这里MyPure 永远不会重新渲染,因为this.childData 表面上是相同的:

    changeChild = () => {
        this.childData.a++;
    }
    
    render() {
        ....
        return (
        ....
            <MyPure data={this.childData} />
    

    这会很好用,因为我们只有在更新内部的东西之后才更新不同的对象:

    changeChild = () => {
        this.setState(oldState => ({
            childData: {
                ...oldState.childData,
                a: oldState.childData.a + 1
            }
        }));
    }
    
    render() {
        ....
        return (
        ....
            <MyPure data={this.state.childData} />
    

    所以我们需要遵守的限制很少: 1.不要在render()中构造data prop(通过调用分离方法显式或隐式) 2. 不要改变对象数据属性

    【讨论】:

    • 谢谢!你提到像 redux 一样返回新对象,但是当通过 props 传递对象时,它会是什么样子?父组件会返回新对象,然后将它传递给子组件?!但随后比较总是会导致真正的意思是总是会发生重新渲染。因此,对对象使用 PureComponent 或 shouldComponentUpdate 要么总是导致错误/总是重新渲染(如果我不返回新对象),要么总是真正意味着永远不会发生重新渲染?!所以,我应该只将它用于原始值或不可变数据,否则我会保证(在某些时候)得到错误
    • 我已经用示例附加了我的答案
    • 谢谢!!一个问题:如果我总是在每次 setState 调用时创建一个新对象,那么通过使用 React.PureComponent 来提高性能的好处不会被过多的内存分配“顶”吗?
    • 不看具体代码就不能说。通常PureComponent 是专门为具有重render() 的组件引入的。因此,您应该已经知道如何确保这种优化对您的项目有意义。
    【解决方案2】:

    浅层比较将是对象内的第一级属性。对于状态,它不应该是同一个对象,因为您应该始终使用新对象调用 setState。你不应该直接改变现有的状态。

    【讨论】:

      猜你喜欢
      • 2019-07-13
      • 1970-01-01
      • 2018-02-22
      • 2018-10-07
      • 2017-01-15
      • 1970-01-01
      • 1970-01-01
      • 2020-03-24
      • 1970-01-01
      相关资源
      最近更新 更多