Как избежать Cannot read property 'map' of undefined при попытке доступа к данным из рендера? - PullRequest
0 голосов
/ 14 июля 2020

React newb ie здесь.

Я попытался разрезать данные в методе fetchData () и попытаться получить к ним доступ из render (). Когда я пытаюсь сопоставить данные внутри рендера, я получаю ошибку «не могу прочитать карту свойств». Что мне не хватает? Я попробовал console.info в методе fetchData () и вижу, что данные извлекаются правильно.

 class BooksComponent extends Component{
        
            constructor(props){
                super(props)
                this.state ={
                    booksData: [],
                    offset: 0,
                    perPage: 3,
                    currentPage: 0,
                }
                this.reserve = this.reserve.bind(this)
                this.fetchData = this.fetchData.bind(this)
            }
        
            fetchData(){
                axios.get('/library')
                  .then(res => {
                    const booksData = res.data
                    const books = booksData.slice(this.state.offset, this.state.offset + this.state.perPage)

                    this.setState({ 
                        pageCount: Math.ceil(booksData.length / this.state.perPage),
                        books })
                  })
            }
            componentDidMount() {
                this.fetchData()
            }
            
            render() {
                return (
                  <div className="App">
                    {this.state.books.map(book => 
                        <React.Fragment key={book.id}>
                        <p>{book.id} - {book.title} - {book.author}</p>
                        <button onClick={() => this.reserve(book.id)}>Reserve {book.quantity}</button>
                        <span>{this.state.booksData.quantity}</span>
                        </React.Fragment>
                    )}
                    <ReactPaginate
                            previousLabel={"prev"}
                            nextLabel={"next"}
                            breakLabel={"..."}
                            breakClassName={"break-me"}
                            pageCount={this.state.pageCount}
                            marginPagesDisplayed={2}
                            pageRangeDisplayed={5}
                            onPageChange={this.handlePageClick}
                            containerClassName={"pagination"}
                            subContainerClassName={"pages pagination"}
                            activeClassName={"active"}/>
                  </div>
                )
            }
        
            reserve(id) {
                console.log("clicked")
                this.setState({
                    booksData: this.state.booksData.map(item => {
                        if (item.id === id) {
                            return { ...item, quantity: (item.quantity - 1) >= 0 ? (item.quantity - 1) : 0};
                        } else {
                            return item;
                        }
                    })
                })
            }
        }
        
        
        export default BooksComponent

Ответы [ 3 ]

1 голос
/ 14 июля 2020

В конструкторе инициализируйте this.state.books пустым массивом:

constructor(props){
    super(props)
    this.state ={
        books: [],
        booksData: [],
        offset: 0,
        perPage: 3,
        currentPage: 0,
    }
    this.reserve = this.reserve.bind(this)
    this.fetchData = this.fetchData.bind(this)
}
0 голосов
/ 14 июля 2020

Попробуйте следующее решение

          {this.state.books ? {this.state.books.map(book => 
                        <React.Fragment key={book.id}>
                        <p>{book.id} - {book.title} - {book.author}</p>
                        <button onClick={() => this.reserve(book.id)}>Reserve 
                      {book.quantity}</button>
                        <span>{this.state.booksData.quantity}</span>
                        </React.Fragment>
             )}: null}

Также проверьте

fetchData(){
                axios.get('/library')
                  .then(res => {
                    const booksData = res.data
                    const books = booksData.slice(this.state.offset, this.state.offset + this.state.perPage)
                  console.log(book)// has data are not
                    this.setState({ 
                        pageCount: Math.ceil(booksData.length / this.state.perPage),
                        books })
                  })
            }
0 голосов
/ 14 июля 2020

Добавьте условную проверку в свой возврат. Если this.state.books ложно, то второй оператор не запустится.

{this.state.books && this.state.books.map(book => 
                        <React.Fragment key={book.id}>
                        <p>{book.id} - {book.title} - {book.author}</p>
                        <button onClick={() => this.reserve(book.id)}>Reserve {book.quantity}</button>
                        <span>{this.state.booksData.quantity}</span>
                        </React.Fragment>
                    )}

edit: также не забудьте установить книги в исходное состояние

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...