I have a component that makes an API request to retrieve data from backend. The request has several dynamic parameters. If one of the parameters is changed then the API call repeats to retrieve new data.
Example:
const Component = ({dep1, dep2}) => {
const [data, setData] = useState(null);
const getData = async () => {
const data = await api.getData({dep1, dep2});
setData(data);
}
useEffect(() => {
getData();
}, [dep1, dep2])
return <div>{JSON.stringify(data)}</div>
}
So my problem is that i have this situation:
dep1
is changed, first request is sentdep2
is changed, second request is sent- second request finished first,
setState
is called first time. - first request finished second,
setState
is called second time.
So in the end i have data from the first request in my current state…
How can i avoid that? How to call setState
in the same order that my requests are sent and not in the order of received responses?
Thank you
2
Answers
Try this solution.
If this not what you expected or if this solution do not work, please let me know.
I’m going to assume you don’t really need the calls to be in order, but instead you just don’t want an earlier call’s result to overwrite a result from a later call.
There are at least a couple of different ways to do it.
Use an
AbortController
and abort it when the deps change; ideally, updateapi.getData
so it use theAbortController
‘AbortSignal
(for instance, it could pass it tofetch
if it usesfetch
). Here’s an example — I movedgetData
into theuseEffect
as there’s no need to recreate the function every time:By making the
AbortSignal
available togetData
, you may be able to prevent work involved in getting the data that would be wasted because of a newer call. But the above works even if for some reason you can’t makegetData
abortable.Use a sequence counter and only save the data if the counter matches the value you had when you started the request. You can track the counter in a ref so that the current value of it is accessible inside
getData
.Other things being equal, I’d use #1, even if I couldn’t update
getData
(but particularly if I could).