0

I have nested objects as described below and updating states.

` interface BookState { name: string authors: AuthorState[] }

interface AuthorState {
    name: string
}


const [bookValues, setBookValues] = useState<BookState[]>(bookStateInitial)


// Add new empty author; which will later be filled from textfields
const onClickAddAuthor = (bookIndex: number) => {
    let newAuthor = { } as AuthorState
    let authors = [...bookValues[bookIndex].authors, newAuthor]
    let newBookState = update(bookValues, { [bookIndex]: { authors: { $set: authors } } })
    setBookValues(newBookState) // ** edited
}


// somewhere i populate bookValues as:
bookValues = [
    {name: "Book-1", authors: [{name: "Author-1"}] },
    {name: "Book-2", authors: [{name: "Author-1"}, {name: "Author-2"}]}
]

`

When I add an author, suppose in "Book-1" index 0, I call the onClickAddAuthor(0), the state updates and UI updates. But when I add an author, suppose in "Book-2" index 1, i call the onClickAddAuthor(1), the state value can be seen updating when printing to console but the UI does not update. I am using https://github.com/kolodny/immutability-helper to update the state.

I expect to add a new empty author on index-1 as well, which should update the state and UI. I tried making deep copies of the book Values and updating the state with that, but it is not working. If it is working in index 0, it should work on other indexes (1, 2, 3 .. ) as well. I am not able to understand.

1 Answers1

0

I tested the posted code with 4 items in bookValues, it seems that the onClickAddAuthor is working as expected. Perhaps the output logic could be checked to see if it updates correctly.

Simple test demo on: stackblitz

import { useState } from 'react';
import './App.css';
import update from 'immutability-helper';

interface AuthorState {
  name: string;
}

interface BookState {
  name: string;
  authors: AuthorState[];
}

const bookStateInitial = [
  { name: 'Book-1', authors: [{ name: 'Author-1' }] },
  { name: 'Book-2', authors: [{ name: 'Author-1' }, { name: 'Author-2' }] },
  { name: 'Book-3', authors: [{ name: 'Author-1' }] },
  { name: 'Book-4', authors: [{ name: 'Author-1' }, { name: 'Author-2' }] },
];

function App() {
  const [bookValues, setBookValues] = useState<BookState[]>(bookStateInitial);
  const onClickAddAuthor = (bookIndex: number) => {
    let newAuthor = { name: 'Test Author' } as AuthorState;
    let authors = [...bookValues[bookIndex].authors, newAuthor];
    let newBookState = update(bookValues, {
      [bookIndex]: { authors: { $set: authors } },
    });
    setBookValues(newBookState);
  };

  return (
    <main className="App">
      <section>
        {[0, 1, 2, 3].map((item) => (
          <button key={item} onClick={() => onClickAddAuthor(item)}>
            {`Test: add author for Book-${item + 1}`}
          </button>
        ))}
      </section>
      <ul>
        {bookValues.map((book) => (
          <li key={book.name}>
            {`name: ${book.name}, authors: ${book.authors
              .map((author) => author.name)
              .join(', ')}`}
          </li>
        ))}
      </ul>
    </main>
  );
}

export default App;
John Li
  • 6,976
  • 3
  • 3
  • 27