简体   繁体   中英

How to update properties of an array nested inside objects in ReactJS

I have simplified my large data set as follows,

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

I want to update the key1 prop of 0th index of someOtherProp, say to "value5".

Tried the following

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

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

Output :

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

But it will convert someOtherProp from array of objects to just nested array. I know that the problem is with "[0] : ..." statement. Not sure how to write it. Please help. New to JS and ReactJS.

The problem you are having is that you're using an object literal instead of an array literal when you define the new someOtherProp.

Try this:

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)
                    ]
            }
}

You're creating an object, not an array, for someOtherProp :

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

Create an array instead. I'd do it before the big object literal:

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

then:

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

But if you want, you can do it inline instead:

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

I don't think you need to force it into one statement.

JS's syntax is not that flexible to do this.

Forcing it too far may hurt cpu-time. (eg when using filter to copy the array to a new one)

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

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

someOtherProp is an array but it is being treated as an object. This a generic approach:

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
            };
        })
    }
};

But as you can see this gets difficult to read and modify. When dealing with nested data you might want to separate concerns for each part of the data. Also there are tools that can be handy such as immer .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM