【问题标题】:Update in one setState property causes another property change automatically in reactjs一个 setState 属性的更新会导致 reactjs 中的另一个属性自动更改
【发布时间】:2020-07-18 19:14:47
【问题描述】:

我在父组件中有一个表格,在子组件中有一个表单字段。我将 onchange 函数作为道具传递,以接收父级子组件上更改的值并将值分配给 state 属性。但是,虽然特定 setState 属性的更改会自动导致另一个 setState 属性的更改。附上示例代码供参考。

 import React, { Component } from 'react';
    import _ from 'lodash';

    state = {
            activeLanguage: localStorage.selectedLanguage,
            obj1: {},
            obj2: []
        };

        componentDidMount = () => {
            this.setState({
                obj1: this.fetchUserDetails()[0],
                obj2: this.fetchUserDetails()

            });
        }

        fetchUserDetails = () => {
            const tempUserTable = [];
            const userInfo = {
                primaryAddress: {
                    addressLine1: 'Test',
                    addressLine2: 'Test',
                    city: 'Test'
                }
            };
            tempUserTable.push(userInfo);
            return tempUserTable;
        }

    handleChange = (value, path) => {
        const { obj1, obj2 } = this.state;
        console.log('Before set method:: ' + obj2);
        //obj1 primaryAddress.addressLine1 value changed from 'Test' to 'Testchange' after next line invoked
        _.set(obj1, path, value); 
        //obj2 primaryAddress.addressLine1 value changed from 'Test' to 'Testchange' automatically
        console.log('After set method:: ' + obj2); 
        this.setState({
            obj1
        });
    };

例如,我从 onChange 函数中的子组件接收值、路径,以使用 setState 更新 obj1。它会自动导致 obj2 发生变化。

示例值更改发生在运行时。

obj1 字段值的 addressLine1 从 'Test' 更改为 'Testchange' - (value='Testchange', path='primaryAddress.addressLine1') - onChange 在父级和 obj1 的 setState 中调用 调用。 obj2 字段值的 addressLine1 从 'Test' 更改为 'Testchange' - 这是自动发生的,无需为此 obj2 调用 setState。

任何帮助将不胜感激。如果需要进一步的信息,请告诉我。

【问题讨论】:

  • 来自Lodash documenation"Note: This method mutates object." 我不确定你想做什么,但无论如何不要改变你的状态。
  • 我没有直接在 this.state 中设置值。刚刚使用 lodash 库来设置对象路径中的值。无论如何感谢您的回答。
  • 为什么要在 componentDidMount 中设置状态??你不应该在那里设置状态。为此使用构造函数
  • 我的意思是如果你使用 lodash 的 set 方法更改对象,那么它会更改对象,无论你是否使用 setState 更改它。这是一个突变。我不是提供答案的人。如果您还没有找到解决方案,您可以在 codesandbox.com 创建一个最小沙箱,以便我们调查问题。
  • 再次感谢。在直接更改对象之前,我已经通过使用 clone deep 更改了我的代码。现在它工作正常。

标签: javascript reactjs ecmascript-6


【解决方案1】:

我不确定您是如何在此示例代码之外获取数据的,但我猜这是因为您设置 obj1obj2 的方式。 obj1obj2[0] 实际上可能指向内存中的相同空间。与数字和字符串等基本类型不同,对象和数组在 JS 中被视为指针。

为了解决这个问题,我们需要将obj2[0] 克隆到它自己的值中。由于您已经在使用 Lodash,因此一种选择是使用他们的 clonedeep 方法。这样的事情可能会解决您的问题:

componentDidMount = () => {
  const data = this.fetchUserDetails();
  this.setState({
    obj1: _.clonedeep(data[0]),
    obj2: data
  });
}

【讨论】:

  • 感谢您的回答。我已经尝试过您在评论中提到的方式。当我在 obj1 中设置值时,obj2 的值仍然在发生变化。不确定是什么原因造成的。
  • 我已经使用了你的方式,并且在任何地方我都使用了克隆深层对象,而不是直接更改它。它工作正常。再次感谢。
猜你喜欢
  • 2020-02-21
  • 2017-04-24
  • 2020-03-05
  • 2021-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-08
  • 1970-01-01
相关资源
最近更新 更多