简体   繁体   English

状态更新后“无法读取未定义的属性'map'”

[英]“cannot read property 'map' of undefined” when state is updated ReactJS

I´m having an issue when udating the state, i´m sure the data i´m getting from the API is right cause i check it with the console.log(), and for some reason the error only happens for searchs with more than 1 letter. 我在查询状态时遇到问题,我确定我从API获取的数据是正确的,因为我使用console.log()进行了检查,并且由于某些原因,该错误仅发生在具有更多内容的搜索中超过1个字母。 I tried solving this using conditionals before the map, mobx and just the normal setState. 我尝试在地图,mobx和普通setState之前使用条件句解决此问题。

This is the code using mobx: 这是使用mobx的代码:

const BookSearch = observer(class BookSearch extends Component{

state = observable({
    query: '',
    books: []
})

searchBooks = (query) =>{
    console.log(query.target.value)
    this.state.query = query.target.value

    BooksAPI.search(query.target.value, 20).then((books) =>{
        console.log(books)
        this.state.books = books;
        console.log(this.state.books)
    })
    console.log(this.state.books)

}

render(){

    const { query } = this.state;

    const bookSearch =  this.state.books.map((book) => 
            <li key={book.id}>
                <div className="book">
                    <div className="book-top">
                        <div className="book-cover" style={{ width: 128, height: 193, backgroundImage: `url(${ book.imageLinks.thumbnail })` }}></div>
                        <div className="book-shelf-changer">
                            <select onChange={(event) => this.props.bookChange(book, event.target.value)}>
                                <option>Move to...</option>
                                <option value="currentlyReading">Currently Reading</option>
                                <option value="wantToRead">Want to Read</option>
                                <option value="read">Read</option>
                                <option value="none">None</option>
                            </select>
                        </div>
                    </div>
                    <div className="book-title">{ book.title }</div>
                    <div className="book-authors">{ book.authors.map((author) => 
                        <span key={ author + book.title } >{ author }</span>
                    )}</div>
                </div>
            </li>
        ) ;


    return(

        <div>   
        <div className="search-books">
            <div className="search-books-bar">
                <Link className="close-search" to='/'>Close</Link>
                <div className="search-books-input-wrapper">
                    {/*
                        NOTES: The search from BooksAPI is limited to a particular set of search terms.
                        You can find these search terms here:
                        https://github.com/udacity/reactnd-project-myreads-starter/blob/master/SEARCH_TERMS.md

                        However, remember that the BooksAPI.search method DOES search by title or author. So, don't worry if
                        you don't find a specific author or title. Every search is limited by search terms.
                    */}
                    <input 
                        type="text" 
                        placeholder="Search by title or author"     
                        onChange={ this.searchBooks}
                    />  
                </div>
            </div>
            <div className="search-books-results">
                <div className="bookshelf">
            <h2 className="bookshelf-title">{ this.state.query }</h2>
            <div className="bookshelf-books">
                <ol className="books-grid">
                    { bookSearch }
                </ol>
            </div>
        </div>
        </div>
        </div>

        </div>
    )
}
})

and this is the searchBooks function without mobx: 这是没有mobx的searchBooks函数:

searchBooks = (query) =>{
  this.setState({ query: query.trim() });

  BooksAPI.search(query, 20).then((books) =>{
    this.setState({ books: books });
  })

  console.log(this.state.books)
}

I have no idea how to solve this issue. 我不知道如何解决这个问题。 thanks for the help. 谢谢您的帮助。

From what I can gather from your code snippet your this.state.books is undefined that's because 从我的代码片段中可以this.state.books是未定义的,这是因为

while setting books in your state you are doing it wrongly it should be 在您的状态下放置书籍时,您做错了

this.setState({books: books})

and immediately after that console.log() wont always give you the updated results. 并且在那之后console.log()不会总是给您更新的结果。

so now your searchBooks will be: 所以现在您的searchBooks将是:

searchBooks = (query) =>{
    console.log(query.target.value)
    this.state.query = query.target.value
    BooksAPI.search(query.target.value, 20).then((books) =>{
        console.log(books)
      this.setState({books}); 
       // reactive way you can also do this.setState({books: books})
    })
}

and if sometime this is empty you can assign it to empty array: 如果某个时间为空,则可以将其分配给空数组:

const {books = []} = this.state
const bookSearch = books.map((book) =>
  <li key={book.id}>
    <div className="book">
      <div className="book-top">
        <div className="book-cover" style={{ width: 128, height: 193, backgroundImage: `url(${book.imageLinks.thumbnail})` }}></div>
        <div className="book-shelf-changer">
          <select onChange={(event) => this.props.bookChange(book, event.target.value)}>
            <option>Move to...</option>
            <option value="currentlyReading">Currently Reading</option>
            <option value="wantToRead">Want to Read</option>
            <option value="read">Read</option>
            <option value="none">None</option>
          </select>
        </div>
      </div>
      <div className="book-title">{book.title}</div>
      <div className="book-authors">{book.authors.map((author) =>
        <span key={author + book.title} >{author}</span>
      )}</div>
    </div>
  </li>
);

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM