ReactJS: Как получить доступ и обновить вложенный объект состояния с помощью динамического ключа? - PullRequest
0 голосов
/ 20 мая 2019

Предположим, у меня есть компонент с состоянием, определенным следующим образом:

this.state = {
    apple:{
        a:1,
        b:2,
    },
    mango:{
        banana : {
            a:1,
            b:2,
        }
    }
}

Если бы я хотел обновить значение вложенного объекта в моем состоянии, я мог бы сделать это с помощью жестко закодированных клавиш, как показано ниже:

cost temp =  { ...this.state['mango'] }
temp['banana']['a'] = 2;

this.setState({mango:temp});

Как мне обновить вложенное значение в моем объекте состояния динамически с ключом? Например, если у меня был путь JSON в точечной или массивной нотации, как я могу обновить состояние моего компонента?

1 Ответ

2 голосов
/ 20 мая 2019

Один из способов добиться этого - получить вложенный объект, который является родительским для поля, на которое нацеливается ваш путь через 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...