Обновление сложного объекта с помощью useState

#javascript #reactjs #object #react-hooks #use-state

Вопрос:

Я пытаюсь выполнить функцию заданного состояния и изменить только одно значение.

Это объект, и, например, я хочу изменить book1 в индексе [0] (так что имя 1) с true на false.

Я не могу понять, как это сделать

все, что я пытаюсь, просто перезаписывает часть объекта

 {
      book1: [
        { name: 1, selected: true },
        { name: 2, selected: false },
        { name: 3, selected: false },
        { name: 4, selected: false },
        { name: 5, selected: true },
      ],
      book2: [
        { name: 1, selected: false },
        { name: 2, selected: false },
        { name: 3, selected: true },
        { name: 4, selected: false },
        { name: 5, selected: true },
      ],
    } 

Комментарии:

1. не по теме, но взгляните на immerjs . Это может облегчить вашу жизнь.

Ответ №1:

Поскольку объект находится в состоянии, вы не можете изменить его напрямую. Вместо этого вам нужно создать копию объекта и любых внутренних объектов (включая массивы), которые вы изменяете. См. Комментарии:

 // Use the callback form because you're updating state based on existing state
setTheObject(original => {
    // Shallow copy the object and book1
    const update = {...original, book1: [...original.book1]};
    // Replace the object at index 0 with a new updated object
    update.book1[0] = {...update.book1[0], selected: false};
    // return the update
    return update;
});
 

Технически это возможно сделать за одну вложенную операцию, но ее гораздо сложнее читать и отлаживать:

 // Use the callback form because you're updating state based on existing state
setTheObject(original => ({
    // Shallow copy the object
    ...original,
    // Shallow copy `book1` while updating index 0 with a copy of the object with the updated property
    book1: Object.assign([], original.book1, {0: {...original.book1[0], selected: false}}),
}));
 

Я не рекомендую этого делать. 😀

Ответ №2:

 const [books, setBooks] = useState({
      book1: [
           { name: 1, selected: true },
           { name: 2, selected: false },
           { name: 3, selected: false },
           { name: 4, selected: false },
           { name: 5, selected: true }
          ],
      book2: [
           { name: 1, selected: false },
           { name: 2, selected: false },
           { name: 3, selected: true },
           { name: 4, selected: false },
           { name: 5, selected: true }
          ]
 });
 

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

 setBooks({
  ...books,
  book1: books.book1.map((book) =>
    book.name === 1 ? { ...book, selected: !book.selected } : book
  )
});
 

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

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