React - Adding component in Map function not adding

Viewed 64

I want to add components into the dom through using the map function over an array. {books.map((book) => <Book/>)}

However, it is not adding anything, it is as if the books array is empty? I printed books using {console.log(books)} and it is non empty. What is wrong here? I have attached my render function.

  render() {
    let books = this.state.books;
    return (<div className="bookshelf">
      <h2 className="bookshelf-title">{this.titles[this.props.shelf]}</h2>
      <div className="bookshelf-books">
        <ol className="books-grid">
          {books.map((book) => <Book/>)}
        </ol>
      </div>
    </div>)
  }

For anyone's info, I obtain the values of book through an api call.

  componentWillMount() {
    BooksAPI.getAll().then((books) => {
      books.forEach((book) => {
        if (this.state.shelf === book.shelf){
          // console.log(book);
          this.state.books.push(book);
        }
      })
    })
  }

Thank you if you understand what is going on.

3 Answers

Whats wrong is that you are directly mutating the state and it doesn't re-render so the change is not reflected in your DOM. use setState to update state

componentWillMount() {
    BooksAPI.getAll().then((books) => {
      const tempBooks = [];
      books.forEach((book) => {
        if (this.state.shelf === book.shelf){
          // console.log(book);
          tempBooks.push(book);
        }
      })
      this.setState(prevState => ({books: [...prevState.books, ...tempBooks]}))
    })
  }
render() {
    let books = this.state.books;
    return (<div className="bookshelf">
      <h2 className="bookshelf-title">{this.titles[this.props.shelf]}</h2>
      <div className="bookshelf-books">
        <ol className="books-grid">
          {books.map((book) => return(<Book/>))}
        </ol>
      </div>
    </div>)
  }

This is the correct fix. I want to add the book into the previous array.

  componentWillMount() {
    BooksAPI.getAll().then((books) => {
      books.forEach((book) => {
        if (this.state.shelf === book.shelf) {
          this.setState(prevState => ({books: [...prevState.books, book]}))
        }
      })
    })
  }
Related