4

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.

2
  • probably the API call hasn't returned and you're using the books array. Can you provide more information, like whole file? Commented Nov 22, 2017 at 5:40
  • 1
    @Ajay Gaur Hi Ajay, the problem has been resolved Commented Nov 22, 2017 at 5:45

3 Answers 3

2

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]}))
    })
  }
Sign up to request clarification or add additional context in comments.

8 Comments

This worked, thank you! I realised I should not directly mutate the state!
kindly dont demand for an acceptance of answer. Why are you so impatient?
This method is wrong, you do are adding an array into an array
Updated the answer
Doesnt matter, I have answered my own question
|
1
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>)
  }

2 Comments

No need of return if its a single line statement,
No need to use return
0

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]}))
        }
      })
    })
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.