Reputation: 1
I am trying to create a search bar for my React.js app.
I have passed getSearch()
method of app.js to child component navigation to retrieve the input value.
In getSearch()
method there is setState({searchTerm:e.target.value})
which is the retrieved value, and then i am calling the fetchData()
method of app.js right after the setState()
withing getSearch()
.
in fetchData()
method this.state.searchTerm
is passed as body for fetch()
, but as I enter something and click enter it gives me the previous value of this.state.searchTerm
and not latest updated value which user inputs.
What am I doing wrong? I am pasting my app.js for review:
import React, { Component } from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import "./App.css";
import Navigation from "./components/Navigation";
import Sidebar from "./components/Sidebar";
import Game from "./components/games";
import Profile from "./components/Profile";
import NotFound from "./components/Notfound";
class App extends Component {
constructor(props) {
super(props);
this.state = {
gameFetched: "false",
searchTerm: ""
};
}
getSearch = e => {
if (e.key === "Enter") {
this.setState({
searchTerm: e.target.value
});
this.fetchIGBD()
}
};
componentDidMount() {
this.fetchIGBD();
}
render() {
return (
<div className="App">
<BrowserRouter>
<div>
<Navigation getSearch={this.getSearch} />
<div id="main-wrapper" className="d-flex">
<Sidebar />
<div id="content">
<Switch>
<Route path="/" component={Game} exact />
<Route path="/profile" component={Profile} />
<Route component={NotFound} />
</Switch>
</div>
</div>
</div>
</BrowserRouter>
</div>
);
}
fetchIGBD = () => {
let url = "http://localhost:8080/api-v3.igdb.com/games";
let data ="fields name,cover,first_release_date,genres.name,platforms.name,total_rating;limit 10;sort popularity;where total_rating > 80;where release_dates.platform = 6;";
let search = "search '"+this.state.searchTerm+"';";
if (search !== "") {
data = data + search
console.log(data)
}
fetch(url, {
method: "POST",
body: data,
headers: {
"Content-Type": "application/json",
"user-key": "myid"
}
})
.then(res => res.json())
.then(json => console.log(json))
.catch(error => console.log(error));
this.setState({
gameFetched: "true"
});
};
}
export default App;
Upvotes: 0
Views: 738
Reputation: 446
Alternate way of calling fetchIGBD
is to use callback of setState
method.It will ensure that you get updated value of searchTerm
.It will triggered after setState
complete.
getSearch = e => {
if (e.key === "Enter") {
this.setState({
searchTerm: e.target.value
},function(){
this.fetchIGBD()
}
);
}
};
Upvotes: 0
Reputation: 1833
You can use following:
this.setState({
searchTerm: e.target.value
}, () => {
this.fetchIGBD()
});
setState
function is async which means it doesn't executes immediately.
Upvotes: 2
Reputation: 196246
If you need to use the state in your fetchIGBD
method you need to call it in the callback
parameter of the setState
. That is required because setState
is asynchronous.
getSearch = e => {
if (e.key === "Enter") {
this.setState({
searchTerm: e.target.value
}, this.fetchIGBD);
}
};
or if you need to pass parameters to it
getSearch = e => {
if (e.key === "Enter") {
this.setState({
searchTerm: e.target.value
}, ()=> this.fetchIGBD(params_here));
}
};
Upvotes: 1