chiche
chiche

Reputation: 25

TypeError: Cannot read property 'map' of null, REACTJS and Axios

I am creating a search bar. The user write his request, and when he press the search button, it's stocked in search, sent via Axios, and return the result at the end. However, I have the good results in my console (the code in the back is ok) but I didn't manage to display the data in my page, because when I add these lines in the return

                    <ul>
                      { this.state.filter.map(book => (
                        <li key={book.id}>{book.title},{book.author}</li>
                      ))}
                    </ul>

, I have this error: TypeError: Cannot read property 'map' of null. What can I change/add in my code in order to display correctly the result of my request please? (I post the picture of the network without the map)

network

import React, {Component} from 'react';
import {
    MDBContainer,MDBCol, MDBBtn, 
  } from 'mdbreact';
import "./acceuil.css";
import axios from 'axios';

class Acceuil extends Component{
  constructor(props){
    super(props);
    this.state = {
      search:'',
      filter: null,
      error:'',
    }
    this.searchTitle = this.searchTitle.bind(this);
  }

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

  searchTitle = (search) => e => {
    console.log(search);
    let formData = new FormData();
    formData.append("search",search);
    const url = "http://localhost:8888/recherche/recherche_titre.php"
    axios.post(url, formData)

    .then(response => response.data)

    .then((data) => {
      this.setState({filter: data});
      console.log(this.state.filter)
    })


    setTimeout(() => {
      this.setState({
        error: '',
      });
    }, 2000);

    e.preventDefault();
  }

    render() {
        const container = {height:530};

        return(
            <div>
                <div className="searchPosition">
                  <MDBCol>
                    <div className="active-pink-3 active-pink-4 mb-4">
                      <input className="form-control" id="search" type="text" placeholder="Search" onChange={this.change} />
                    </div>
                  </MDBCol>
                </div>
                <div>
                  <MDBBtn  onClick={this.searchTitle(this.state.search)} color="dark" size="lg">Search</MDBBtn>

                <ul>
                  { this.state.filter.map(book => (
                  <li key={book.id}>{book.title},{book.author}</li>
                  ))}
                </ul>
            </div>

        );
    }
}

export default Acceuil;

Upvotes: 0

Views: 5259

Answers (2)

Vitalij Kornijenko
Vitalij Kornijenko

Reputation: 559

One of the ways to fix this issue is to set the filler to an array in the constructor.

constructor(props){
  super(props);
  this.state = {
    search:'',
    filter: [], // <== THIS CHANGED
    error:'',
  }
  this.searchTitle = this.searchTitle.bind(this);
}

Or you can change the render method to ignore null filter, which I personally prefer since you know whether your request is loaded or not

this.state.filter ? this.state.filter.map(book => ...) : <em>Loading...</em>;

Upvotes: 2

norbitrial
norbitrial

Reputation: 15166

Probably one option is to check for null values before using .map().

Try with using && as the following:

<ul>
   { this.state.filter && this.state.filter.map(book => (
       <li key={book.id}>{book.title},{book.author}</li>
   ))}
</ul>

I hope this helps!

Upvotes: 2

Related Questions