如何在ReactJS中更新嵌套在对象内部的数组的属性

时间:2020-03-06 15:11:56

标签: javascript reactjs

我将大型数据集简化如下,

let state = {
    someProp: {
        someOtherProp: [
            {
                key1: "value1",
                key2: "value2"
            },
            {
                key1: "value3",
                key2: "value4"
            }
        ]
    }
}

我想更新someOtherProp的第0个索引的key1属性,例如“ value5”。

尝试了以下

let newState = {
    ...state, 
        someProp: 
            {...state.someProp, 
                someOtherProp: 
                    {...state.someProp.someOtherProp, 
                        [0]: 
                           {...state.someProp.someOtherProp[0], 
                               key1 : "value5"
                           }
                    }
            }
}

document.write(JSON.stringify(newState));

输出:

    {
       "someProp": {
          "someOtherProp": {
               "0": {
                      "key1":"value5",
                      "key2":"value2"
                    },
               "1": {
                       "key1":"value3",
                       "key2":"value4"
                    }
           }
        }
      }

但是它将把someOtherProp从对象数组转换为嵌套数组。 我知道问题出在“ [0]:...”语句上。不确定如何编写。 请帮忙。 JS和ReactJS的新手。

4 个答案:

答案 0 :(得分:2)

您遇到的问题是,在定义新的someOtherProp时,您正在使用对象文字而不是数组文字。

尝试一下:

let newState = {
    ...state, 
        someProp: 
            {...state.someProp, 
                someOtherProp: 
                    [
                       // create a new first element, using the existing, and overridding key1
                       {...state.someProp.someOtherProp[0], 
                               key1 : "value5"
                       },
                       // append all other someOtherProps except for the first one
                       ...state.someProp.someOtherProp.slice(1)
                    ]
            }
}

答案 1 :(得分:2)

您正在为someOtherProp创建一个对象,而不是一个数组:

someOtherProp: 
    {...state.someProp.someOtherProp, 
        [0]: 
           {...state.someProp.someOtherProp[0], 
               key1 : "value5"
           }
    }

改为创建一个数组。我会在大对象字面量之前这样做:

const someOtherProp = [...state.someProp.someOtherProp];
someOtherProp[0] = {
    ...state.someProp.someOtherProp[0]
    key1 : "value5"
};

然后:

const someOtherProp = [...state.someProp.someOtherProp];
someOtherProp[0] = {
    ...state.someProp.someOtherProp[0]
    key1 : "value5"
};
let newState = {
    ...state, 
        someProp: 
            {...state.someProp,  someOtherProp}
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^
}

但是,如果您愿意,可以改为内联:

someOtherProp: 
    [
// −^   {...state.someProp.someOtherProp[0],      // Note this is first
            key1 : "value5"
        },
        ...state.someProp.someOtherProp.slice(1)  // Note skipping the first
    ]
// −^

答案 2 :(得分:1)

我认为您无需将其强制为一项声明。

JS的语法执行起来不太灵活。

强行将其过长可能会损害CPU时间。 (例如,使用过滤器将数组复制到新数组时)

const newSomeOtherProp = state.someProp.someOtherProp.slice();
newSomeOtherProp[0] = {...newSomeOtherProp[0], key1: "value5"};

const newState = { 
  ...state,
  someProps: { 
    ...state.someProp,
    someOtherProp: newSomeOtherProp
  }
};

答案 3 :(得分:0)

someOtherProp是一个数组,但被视为对象。这是一种通用方法:

const index_to_modify = 0;
const key_to_modify = "key1";
const new_value = "value5";

const newState = {
    ...state,
    someProp: {
        ...state.someProp,
        someOtherProp: state.someProp.someOtherProp.map((item, index) => {
            if (index !== index_to_modify) {
                return item;
            }

            return {
                ...item,
                [key_to_modify]: new_value
            };
        })
    }
};

但是如您所见,这变得很难阅读和修改。处理嵌套数据时,您可能需要针对数据的每个部分分离关注点。还有一些方便的工具,例如immer