ReactJS: Обновление массива внутри состояния объекта не вызывает повторного рендеринга - PullRequest
0 голосов
/ 28 апреля 2020

У меня есть функция реагирования, которая имеет объект состояния apiDATA. В этом состоянии я сохраняю объект структуры:

{
name : "MainData", description: "MainData description", id: 6, items: [
{key: "key-1", name : "Frontend-Test", description: "Only used for front end testing", values: ["awd","asd","xad","asdf", "awdr"]},
{key: "key-2", name : "name-2", description: "qleqle", values: ["bbb","aaa","sss","ccc"]},
...
]
}

Мой интерфейс отображает основные данные из объекта в качестве заголовков, а затем я отображаю каждый элемент в items. Для каждого из этих элементов мне нужно отобразить values и сделать их редактируемыми. Я приложил изображение ниже.

enter image description here

Теперь, как вы можете видеть, у меня есть кнопка «плюс», которую я использую для добавления нового values. Я использую модальный режим для этого, и когда я вызываю функцию для обновления состояния, она работает нормально и выполняет рендеринг правильно. Теперь для каждого из слов в values у меня есть этот чип с кнопкой удаления на их стороне. И функция удаления для этой кнопки выглядит следующим образом:

const deleteItemFromConfig = (word, item) => {
    const index = apiDATA.items.findIndex((x) => x.key === item.key);

    let newValues = item.value.filter((keyWord) => keyWord !== word);

    item.value = [...newValues];

    api.updateConfig(item).then((res) => {
      if (res.result.status === 200) {
        let apiDataItems = [...apiDATA.items];
        apiDataItems.splice(index, 1);
        apiDataItems.splice(index, 0, item);
        apiDATA.items = [...apiDataItems];
        setApiDATA(apiDATA);
      }
    });
  };

К сожалению, эта функция не выполняет повторную визуализацию при обновлении состояния. И это только перерисовывается, когда я обновляю какое-то другое состояние. Я знаю, что код немного дурацкий, но я попробовал несколько вещей, чтобы сделать его заново, и я не могу обойти это. Я знаю, что это как-то связано с React, который не рассматривает это как правильное обновление, поэтому он не рендерится, но я понятия не имею, почему.

Ответы [ 2 ]

1 голос
/ 28 апреля 2020

Не обновляется, потому что вы изменяете массив items внутри apiDATA, и React выполняет повторную визуализацию только в случае изменения указателя на apiDATA. React не сравнивает все элементы внутри apiDATA.

. Для создания обновлений React необходимо создать новый apiDATA.

Попробуйте:

      if (res.result.status === 200) {
        let apiDataItems = [...apiDATA.items];
        apiDataItems.splice(index, 1);
        apiDataItems.splice(index, 0, item);
        setApiDATA(prevState => {
            return {
                ...prevState,
                items: apiDataItems
            }
       });
      }
0 голосов
/ 28 апреля 2020

Использование splice не очень хорошая идея, так как оно мутирует массивы на месте, и даже если вы создаете копию с помощью let apiDataItems = [...apiDATA.items];, это все еще мелкая копия, которая имеет оригинальную ссылку на вложенные значения.

Один из вариантов - обновить данные с помощью map:

const deleteItemFromConfig = (word, item) => {
  api.updateConfig(item).then((res) => {
    if (res.result.status === 200) {
      const items = apiDATA.items.map(it => {
        if (it.key === item.key) {
          return {
            ...item,
            values: item.value.filter((keyWord) => keyWord !== word)
          }
        }
        return item;
      })

      setApiDATA(apiData => ({...apiData, items});
    }
  });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...