首页 > 解决方案 > React: ".map is not a function" Issue

问题描述

There is the sample code that I received this error:

I'm getting this error via Search component. I assume , I'm overriding state.books to the object. However, can't find the solution as a junior. How should I update state.books correctly ?

GetData.js

import React, { Component } from 'react';
import Search from '../pages/Search';
import CreateForm from '../components/CreateForm';
import axios from 'axios';

class GetData extends Component {
  state = {
    books: []
  };

  componentDidMount(){
    axios.get('/api/books/').then(res => {
      console.log(res);
      this.setState({
        books: res.data
      });
    });
  }

  addBook = (book) => {
    let books = [...this.state.books, book]
    axios.post('/api/books/', books).then(res => {
      console.log(res);
      this.setState({
        books: res.data
      });
    });
  }

  render() {
    return (
      <div className="app">
        <Search books={this.state.books} />
        <CreateForm addBook={this.addBook}/>
      </div>
    );
  }
}
export default GetData;

Search.js

import React from 'react';

const Search = ({books}) => {
  const bookElements = books.map(book => {
    return(
      <div className="book-data" key={book._id}>
        <div>{book.author}</div>
        <div>{book.publication}</div>
        <div>{book.publisher}</div>
      </div>
    )
  })

  return(
    <div className="book-elements">
      {bookElements}
    </div>
  )
}

export default Search;

CreateForm.js

import React, {Component} from 'react';

class CreateForm extends Component {
  state = {
    author: null,
    publication: null,
    publisher: null,
  };

  handleChange = (e) => {
    this.setState({
      [e.target.id]: e.target.value
    })
  }

  handleSubmit = (e) => {
    e.preventDefault();
    this.props.addBook(this.state);
  }

  render () {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          <label htmlFor="author">Author:</label>
          <input type="text" id="author" onChange={this.handleChange}/>
          <label htmlFor="publication">Publication:</label>
          <input type="text" id="publication" onChange={this.handleChange}/>
          <label htmlFor="publisher">Publisher:</label>
          <input type="text" id="publisher" onChange={this.handleChange}/>
          <button>Submit</button>
        </form>
      </div>
    )
  }
}

export default CreateForm;

api.js

const express = require('express');
const router = express.Router();
const Book = require('../models/book');

router.get('/books', function(req, res, next){
    Book.find({}).then(function(books){
        res.send(books);
    }).catch(next);
});

// Add a new book to the database.
router.post('/books', function(req, res, next){
    Book.create(req.body).then(function(book){
        res.send(book);
    }).catch(next);
});

// Update a book in the database.
router.put('/books/:id', function(req, res, next){
    Book.findByIdAndUpdate({_id: req.params.id}, req.body).then(function(){
        Book.findOne({_id: req.params.id}).then(function(book){
            res.send(book);
        });
    }).catch(next);
});

// Delete a book from the database.
router.delete('/books/:id', function(req, res, next){
    Book.findByIdAndRemove({_id: req.params.id}).then(function(book){
        res.send(book);
    }).catch(next);
});

module.exports = router;

and model.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// CREATE BOOK-DATA SCHEMA and MODEL
const bookSchema = new Schema({
    author: {
        type: String,
        required: [false, 'Author field is required'] 
    },

    publication: {
        type: String
    },

    publisher: {
        type: String
    },

    /*available: {
        type: Boolean,
        default: false
    }*/
});

const Book = mongoose.model('book', bookSchema);

module.exports = Book;

Added api.js and that's model. Is there missing something ? Added CreateForm.js and there is the place where I'm passing the new data. Is state definition wrong ?

标签: javascriptreactjs

解决方案


This might be because books is not Array. Always follow practice of checking Array and then map like.

const bookElements = Array.isArray(books) && books.map(book => {
    return( ...)

or

 const bookElements = Array.isArray(books) ? books.map(book => {
        return( ...) : // if not array then show some msg may b error/loader/empty list depending upon use case

For better solution provide more details like API reply etc


推荐阅读