useState Обновление состояния объекта дочернего массива не работает - PullRequest
0 голосов
/ 09 ноября 2019

У меня есть это состояние в моем компоненте React ->

const [employeeState, setEmployee] = useState({
        "empName": null,
        "Age": null,
        "depts": [], //depts is an array of objects
        "groups": [] //group is an array of objects
});

У меня есть отдельное состояние для узлов и групп, как показано ниже ->

const depts = {
        "name": "some name",
        "code": "s123",
}
const [deptState, setDeptState] = useState([
        { ...depts},
]);

То же самое для групптоже ....

Теперь, когда я пытаюсь установить состояние сотрудника для какого-то btn клика, как показано ниже, оно не обновляет и не сохраняет свойство depts и groups, поскольку оно пустое ->

const deptsLst = [...deptState];
const groupsLst = [...groupstate];
console.log(depsLst); // this will print the results as expected
console.log(groupsLst); // this will print the results as expected
setEmployee({
      ...employeeState,
      ['depts']: deptsLst ,
      ['groups']: groupsLst ,
})
 console.log(employeeState);// this will show depts and groups as empty only

Я новичок в этом распространяемая переменная концепция копирования. Что я здесь не так делаю?

Ответы [ 3 ]

1 голос
/ 09 ноября 2019

Вы заявляете, что «я новичок в этой концепции копирования переменных распространения» ... вы не только новичок в операции распространения, но ваш код демонстрирует, что вы не имеете базового понимания этого, я думаю. Вы используете операторы спреда поверх операторов спреда поверх имен свойств компьютера, и все это без причины.

Вы также используете состояние React для управления объектом сотрудника, а затем используете состояние React для управления свойствами массива вобъект сотрудника. Если вы уже выполняете управление состоянием для объекта сотрудника, зачем поддерживать состояние отдельных свойств?

Хорошо, пара разбивок вашего кода:

const depts = {
        "name": "some name",
        "code": "s123",
}
const [deptState, setDeptState] = useState([
        { ...depts},
]);

Над вами клонируют объект без причины. .

При управлении состоянием React вам нужно только клонировать объекты, чтобы вызвать событие рендеринга. Клон создает новый объект с новой ссылкой в ​​памяти, «реагирует» на изменения ссылки на объект и запускает событие изменения состояния. React не способен отслеживать каждое свойство сложного объекта, особенно элементы массива, чтобы увидеть, изменилось ли значение.

Приведенного ниже кода будет достаточно, вы инициализируете состояние, вам не нужно клонировать:

const [deptState, setDeptState] = useState([{
        "name": "some name",
        "code": "s123",
}]);

Следующий код:

setEmployee({
      ...employeeState,
      ['depts']: deptsLst ,
      ['groups']: groupsLst ,
})

Здесь вы пытаетесь использовать оператор распространения, чтобы клонировать объект «employeeState» и обновить новые значения для ключа свойства depts и groups ключ свойства. Вы используете «Вычисленные имена свойств» для ключей свойств без причины.

Этого достаточно:

setEmployee({
      ...employeeState,
      depts: deptsLst ,
      groups: groupsLst
})

Вы также создаете ненужное состояние:

const [deptState, setDeptState] = //..rest of code omitted

Здесь выне понимаю, что изменения состояния React происходят асинхронно:

setEmployee({
      ...employeeState,
      ['depts']: deptsLst ,
      ['groups']: groupsLst ,
})
console.log(employeeState);

Приведенный выше код фактически изменил employeeState, просто не время вашего console.log(employeeState);

Хорошо, так что для начала я создал CodePen , чтобы вы могли понять, как изменяется состояние.

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

const [employee, setEmployee] = React.useState({
    "empName": 'Jane Doe',
    "Age": 33,
    "depts": [
        {
            "name": "some name",
            "code": "s123",
        }
    ]
});

Здесь я добавляю отдел к сотруднику, обратите внимание, что я клонирую только объект сотрудникатриггер React для обнаружения полного изменения ссылки на объект, React не знает, что я изменил свойство depts массив, но новое состояние действительно имеет мое новое значение, которое я нажал oв массиве отделов:

function exampleUpdatingEmployee() {
    employee.depts.push({
        "name": "some new dept",
        "code": "876",
    });
    setEmployee({ ...employee });
}
1 голос
/ 09 ноября 2019

Вы можете сделать:

setEmployee({
  ...employeeState,
  depts: deptsLst,
  groups: groupsLst
})

для обновления вашего employeeState. Вы, вероятно, не увидите обновление с console.log, которое у вас есть сразу после этого, поскольку оно будет выполнено до обновления состояния. Вы можете убедиться, что employeeState обновлено с помощью функции useEffect, например:

  useEffect(() => {
    console.log(employeeState)
  }, [employeeState])

Оператор распространения - это способ копирования массивов в ES6 без передачи ссылки на вашу копию, чтобы вы могли изменить ее. массив без этих изменений, отображаемых в другом массиве. Вы можете прочитать об этом подробнее здесь: Ссылка и копирование объектов и массивов .

0 голосов
/ 09 ноября 2019

если depts и group являются массивами объектов, вы должны использовать оператор распространения таким образом, чтобы копировать значения:

setEmployee({
      ...employeeState,
      depts: [...deptState],
      groups: [...groupstate]
});

, поэтому если:

const employeeState = {status: 'hungry'};
const deptState = ['one', 'two'];
const groupstate = ['y', 'k', 'o'];

, то первый код,после распространения, это как:

setEmployee({
   status: 'hungry',
   depts: ['one', 'two'],
   groups: ['y', 'k', 'o']
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...