I have the following useEffect hook in a react component that fetches data from a api. http
is an axios instance. I have a react use State hook const [inputsData, setInputsData] = useState(false);
.
useEffect(() => {
if (active.id) {
http.get(`/stock/${title}/${active.id}`).then((response) => {
setInputsData(response.data);
console.log(inputsData);
});
}
}, [title, active.id, refresh]);
The data shown is to be refreshed and rerendered whenever the title (which is a URL Route Parameter), active.id (active is a react state that stores the data of the current item to be shown) or the refresh variable changes.
But, eventhough I have confirmed that the data coming from the api is correct, when I set the state of the component, when I console.log
it, it shows the old state. The state being rendered is also the old one and I have to renavigate to the active item or refresh the page in order to see the correct data.
Basically:
I click on a, it shows the data for a.
I click on b, it shows the data for a.
I click on c, it shows the data for b.
Any idea on why the data is not being set correctly?
I tried running it twice to simulate renavigating to the active item. That didn’t work.
I tries setting the state to false
and then setting it to the new data. That didn’t work.
I tried using setTimeout
on the setState because I thought delaying it might help. That didn’t work.
Edit:
I removed useEffect
. My code is now:
if (active.id && !inputsData) {
http.get(`/stock/${title}/${active.id}`).then((response) => {
setInputsData(response.data);
console.log(inputsData);
});
}
This replaces the useEffect.
inputsData
is set to false on the button click and on the rerender, the new value for it is fetched from the api.
Thanks to user mmm for linking the article.
3
Answers
I removed useEffect. My code is now:
This replaces the useEffect. inputsData is set to false on the button click and on the rerender, the new value for it is fetched from the api. Thanks to user mmm for linking the article.
you are probably having a race condition where here is what happens:
1- you have the current state
2- you make a change that triggers the useEffect but with the old data (changing that
refresh
state probably?)3- you make the actual change you need, like changing the
title
oractive.id
4- since you had 2 requests, the one from
2
and the one from3
and since these are asynchronous actions, the Promise from3
might resolve before the Promise from2
, thus the state will use the last updated state which is from2
in this caseIf this was the problem, you can solve that by using boolean flag
so it will look like this:
useState hook is asynchronous , so sometimes you will see old state data.
for getting new data we can rewrite code like this
setInputsData((oldState) => {…oldState, …response.data} );