Один из способов добиться этого - получить вложенный объект, который является родительским для поля, на которое нацеливается ваш путь через Array#reduce
:
const nestedObject = path
.slice(0, -1)
.reduce((object, part) => (object === undefined ? undefined : object[part]), { ...state })
А затем обновите последний ключ / значение nestedObject
с помощью последнего ключа вашего пути:
/* Get last part of path, and update nestedObject's value for this key, to 2 */
const [pathTail] = path.slice(-1);
nestedObject[pathTail] = 2;
Следующий фрагмент показывает эти две идеи вместе:
/* Path of nested field to update, in array notation */
const path = ['mango', 'banana', 'a'];
/* Components state */
const state = {
apple: {
a: 1,
b: 2,
},
mango: {
banana: {
a: 1,
b: 2,
}
}
};
const stateClone = { ...state };
/* Aquire the parent object (ie banana) of the target field (ie a) */
const nestedObject = path
.slice(0, -1)
.reduce((object, part) => (object === undefined ? undefined : object[part]), stateClone)
if (nestedObject !== undefined) {
/* Obtain last key in path */
const [pathTail] = path.slice(-1);
/* Update value of last key on target object to new value */
nestedObject[pathTail] = 2;
}
/* Display updated state */
console.log('Updated state:', stateClone)
/* Call this.setState: */
// this.setState(stateClone);
Обновление
Вот некоторые дополнительные подробности, описывающие, как работает reduce()
часть ответа:
path
/* slice obtains ['mango', 'banana'], seeing -1 clips last item */
.slice(0, -1)
/* reduce iterates through each part of array ['mango', 'banana']
where at each iteration we fetch the corresponding nested object
of the { ...state } object that's passed in */
.reduce((object, part) => {
/* At iteration 1:
object has two keys, 'apple' and 'mango'
part is 'mango'
object is defined, so return object['mango'] for first iteration
At iteration 2:
object passed from last iteration has one key, 'banana'
part is 'banana'
object is defined, so return object['banana'] for second iteration
Reduce complete:
we return object['banana'], which is the same as state['mango']['banana']
*/
if(object === undefined) { return undefined; }
return object[part]
}, stateClone)