Reputation: 25
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)
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
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
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