I want to fetch the data when the search button gets clicked, for that I made a function, on that I changed the state of data and after that i fetched the data. But the problem is in the fetching link that i had provided, it is taking the initial value of that data state not the value that i has been changed after the search button clicked. Code:
<form className="d-flex">
<input
onChange={(e) =>
this.setState({ instant_data: e.target.value })
}
className="form-control me-2"
type="search"
placeholder="Search"
aria-label="Search"
/>
<button
className="btn btn-outline-success"
type="submit"
onClick={this.searchNews}
>
Search
</button>
</form>
constructor() {
super();
this.state = {
instant_data: "",
data: "",
search_data: [],
};
}
searchNews = async (e) => {
e.preventDefault();
this.setState({
data: this.state.instant_data,
});
const link = `https://newsapi.org/v2/everything?q=${this.state.data}&apiKey=API_KEY`;
const raw_data = await fetch(link);
const data = await raw_data.json();
console.log(data);
};
From the documentation;
setState() does not immediately mutate
this.statebut creates a pending state transition. Accessingthis.stateafter calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.
Suggestion -> passing a callback function:
this.setState({
data: this.state.instant_data,
}, () => {
const link = `https://newsapi.org/v2/everything?q=${this.state.data}&apiKey=API_KEY`;
const raw_data = await fetch(link);
const data = await raw_data.json();
console.log(data);
});
It is because this.setState is not immediate change, sometimes it takes some time to set it so you should not use this.state.data but use this.state.instant_data instead like:
const link = `https://newsapi.org/v2/everythingq=${this.state.instant_data}&apiKey=API_KEY`;
Change your input to:
<input
onChange={(e) => this.setState({ instant_data: e.target.value })}
className="form-control me-2"
type="search"
placeholder="Search"
aria-label="Search"
value={this.state.instant_data} <--- added this here
/>
And change your searchNews function to:
searchNews = async (e) => {
e.preventDefault()
const link = `https://newsapi.org/v2/everything?q=${this.state.instant_data}&apiKey=API_KEY`
const raw_data = await fetch(link)
const data = await raw_data.json()
console.log(data)
}
Gist
// this is async operation
this.setState({
data: this.state.instant_data,
});
So you end up making the call first and then update the state variable data