setStateで配列更新するパターン

とにかく、元のstateにある配列を直接いじらないこと。

class Shelf extends Component {
  constructor(props) {
    super(props);
    this.state = {
      books: [{ id: 0, title: "Never Ending Story" }],
      controlId: 1,
    };
  }
  
  addBook(title) {
    const { books, controlId } = this.state;
    const newBook = { id: controlId, title };
    const nextId = controlId + 1;
    
    // pattern 1: push
    books.push(newBook);
    this.setState({ books, uniqueId: nextId });

    // pattern 2: concat
    const newBooks = books.concat([newBook]);
    this.setState({ books: newBooks, uniqueId: nextId });

    // pattern 3: spread operator
    const newBooks = [...books, newBook];
    this.setState({ books: newBooks, uniqueId: nextId });

    // pattern 4: slice
    const newBooks = this.state.books.slice();
    newBooks.push(newBook);
    this.setState({ books: newBooks, uniqueId: nextId });
  }

...