React - удалить вложенный элемент массива с помощью вызова функции setState

Я пытаюсь удалить (полу) глубоко вложенный элемент из массива с помощью setState, но, похоже, он не работает. Мое состояние устроено следующим образом:

state = {
  currentSeries: null,
  currentRowIndex: null,
  rows: [
    {
      id: shortid.generate(),
      nodes: [], 
      series: [], // array with item I want to remove
    },
  ],
};

и мой вызов удаления элемента:

onRemoveModelElementClick = (rowId, modelElementId) => {
  this.setState((prevState) => {
    const index = prevState.rows.findIndex(x => x.id === rowId);
    const series = prevState.rows[index].series.filter(s => s.id !== modelElementId);
    return series;
  });
};

Я пытался распространить оставшееся состояние несколькими способами, но, похоже, оно не обновляется должным образом. I rowId и modelElementId верны, и я могу убедиться, что они отфильтровывают правильный элемент. У меня просто проблемы с тем, что вернуть. Я знаю, что это что-то простое, но хоть убей, я не могу этого понять.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
923
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Я бы порекомендовал использовать .map, чтобы упростить восприятие. Затем вы можете написать это так:

onRemoveModelElementClick = (rowId, modelElementId) => {
  const updatedRowsState = this.state.rows.map(row => {
    // this is not the row you're looking for so return the original row
    if (row.id !== rowId) {
      return row;
    }

    const filteredSeries = row.series.filter(s => s.id !== modelElementId);
    return {
      // spread properties (id, node, series)
      ...row,
      // overwrite series with item filtered out
      series: filteredSeries,
    };
  });

  // since rest of the state doesn't change, we only need to update rows property
  this.setState('rows', updatedRowsState);
}

Надеюсь, это поможет, и дайте мне знать, если у вас есть какие-либо вопросы.

Это отличная идея. То, что вы написали, не работает из коробки, но это дало мне решение, поэтому я принимаю его. Я также добавлю ответ о том, что я сделал, чтобы заставить его работать.

cbutler 10.04.2019 08:01

Я думаю, проблема здесь в том, как ваш код использует setState. Функция setState должна возвращать объект. Предполагая, что ваши функции фильтрации верны, как вы описываете, верните объект для обновления состояния:

return { series };

документация setState

Вот что я сделал, чтобы заставить его работать, если это может помочь кому-то еще:

onRemoveModelElementClick = (rowId, modelElementId) => {
  this.setState((prevState) => {
    const updatedRowState = prevState.rows.map((row) => {
      if (row.id !== rowId) {
        return row;
      }

      const filteredSeries = row.series.filter(s => s.id !== modelElementId);
      return {
        ...row,
        series: filteredSeries,
      };
    });
    return {
      rows: updatedRowState,
    };
  });
};

Спасибо Дому за прекрасную идею и логику!

Другие вопросы по теме