Обновление значений объекта useState с помощью карты

Я использую useState внутри useContext, у меня есть кнопка внутри компонента, который, когда пользователь нажимает кнопку, добавит новый элемент на страницу, который, в свою очередь, создаст новый объект в массиве useState следующим образом:

  const [items, setItems] = useState([])

  const addItem = () => {
    setItems((items) => [...items, {
      id: items.length,
      key: randomKey(),
      selected: false,
      FG_value: 0,
      FS_value: 0,
      FB_value: 'auto',
      AS_value: 'auto',
      OR_value: 0,
    }])
  }

Теперь, когда пользователь нажимает на элемент на странице, он переключает «выбранное» значение false/true следующим образом:

  const editItem = (value) => {
    const selectedItem = items.map((item) => item.key === value ? {
      ...item,
      selected: !item.selected
    } : item)
    setItems(selectedItem)
  }

Приведенный выше код работает так, как должен, но я застреваю в том, что когда пользователь щелкает элемент, а затем щелкает другой элемент, оба значения «выбранных» элементов являются истинными. Я пытаюсь правильно написать код, чтобы при щелчке элемента и item.key === value переключалось «выбрано» и устанавливалось для всех остальных значений items.selected значение false. Таким образом, в основном, если пользователь щелкает первый элемент, он выбран, а затем, если он щелкает другой элемент, он отменяет выбор первого элемента, а затем выбирает новый элемент, по которому щелкнули.

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Сравнение структур данных: Массивы и объекты в Javascript
Сравнение структур данных: Массивы и объекты в Javascript
Итак, вы изучили основы JavaScript и хотите перейти к изучению структур данных. Мотивация для изучения/понимания Структур данных может быть разной,...
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Прошлая статья была первой из цикла статей о создании системы электронной коммерции с использованием Keystone.js, и она была посвящена главным образом...
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
Стоит ли использовать React в 2022 году?
Стоит ли использовать React в 2022 году?
В 2022 году мы все слышим о трендах фронтенда (React, Vue), но мы не знаем, почему мы должны использовать эти фреймворки, когда их использовать, а...
0
0
33
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Если элементы не удаляются из массива, вы можете сделать:

const [items, setItems] = useState([])
const [selectedItemIndex, setSelectedItemIndex] = useState(-1);
// ...
{items.map((item, i) => (
  <other item JSX>
  <button onClick={() => setSelectedItemIndex(i === selectedItemIndex ? -1 : i)}
))}

Теперь, где бы вы ни использовали item.selected в настоящее время, вместо этого сравните индекс итерируемого элемента с selectedItemIndex.

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

RobbieC 23.04.2022 19:16
Ответ принят как подходящий

Как и в CertainPerformance, я бы сохранил отдельное состояние для выбранного элемента. Однако, если вы хотите изменить свою функцию editItem, чтобы переключать один элемент (с выбранного на невыбранный или с невыбранного на выбранный) и сделать все остальные элементы невыбранными (т.е. выбранным является false), вы можете написать это так:

const editItem = (value) => {
  const updatedItems = items.map((item) => item.key === value ? {
    ...item,
    selected: !item.selected
  } : {
    ...item,
    selected: false
  })
  setItems(updatedItems)
}

Я переименовал selectedItem в updatedItems, потому что из-за selectedItem казалось, что переменная предназначена только для одного элемента, хотя на самом деле она была для всех элементов.

Дайте мне знать, если это поможет.

Спасибо, это отвечает на мой вопрос и работает без необходимости переписывать какой-либо другой код.

RobbieC 23.04.2022 19:16

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