Как добавить или удалить элемент из массива состояний в реакции

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

Это код, который я использовал

this.setState(prevState => ({
  this.state.activeItemList: [...prevState.activeItemList, newItem]
}))

Интерфейс

interface IState {     activeItemList?: IItem[] | null;  }

Это правильный путь?

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

Ответы 3

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

  1. Вы используете версию обратного вызова setState, и
  2. Вы создаете новый массив, а не изменяете существующее состояние.

Идеально!

Вы также можете использовать concat вместо распространения:

this.setState(prevState => ({
  this.state.activeItemList: prevState.activeItemList.concat(newItem)
}))

но опять же, ваш путь, вероятно, идиоматичен в современном мире. Кроме того, если бы newItem был массивом (например, activeItemList был задуман как массив массивов), concat распространил бы его, что было бы нехорошо.

На самом деле, я бы написал так

this.setState(prevState => ({
  ...prevState,
  activeItemList: [...prevState.activeItemList, newItem]
}))

С текущим определением IState это означает то же самое, но если IState когда-либо изменится, я готов. Кроме того, в коде подчеркивается, что все, что он делает, это добавляет newItem, а не стирает что-либо еще.

Удаление я бы реализовал как:

this.setState(prevState => ({
  ...prevState,
  activeItemList: prevState.activeItemList.filter(item => item !== oldItem)
}))

Я получаю эту ошибку: Argument of type '(prevState: Readonly<IState>) => { activeItemList: (IItem | undefined)[]; }' is not assignable to parameter of type 'IState | ((prevState: Readonly<IState>, props: Readonly<IProps>) => IState | Pick<IState, "activeItemList"> | null) | Pick<IState, "activeItemList"> | null'.

Ankit Jayaprakash 27.05.2019 16:56

Извините, исправил некоторые опечатки.

Michael Lorton 28.05.2019 07:21
Ответ принят как подходящий

Во-первых, вам нужно проверить, не был ли массив нулевым или неопределенным, тогда вы можете добавить новый элемент в существующий массив, иначе создайте массив с помощью newItem.

 this.setState((prevState) => ({
        ...prevState,
        activeItemList: prevState.activeItemList ? [...prevState.activeItemList, newItem] : [newItem],
    }));

Похоже, вы проверяете, существует ли prevState.activeItemList или нет, не проверяя, массив это или нет. Лучшим подходом будет запуск state = { activeItemList: [] }, который изначально гарантирует, что это массив, вместо проверки, верно @kwdowik?

Dani Vijay 27.05.2019 17:32

Конечно, вы можете назначить пустой массив для activeItemList в конструкторе, как вы написали, но я предполагаю, что машинописный текст по-прежнему будет концентрировать внимание на том, что activeItemList может быть неопределенным или нулевым. @DaniVijay

kwdowik 27.05.2019 18:30

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