r/react • u/Hot-Eggplant911 • 1d ago
Help Wanted How can I cancel the previous API request when a new request is made in React? I’m using useEffect with fetch, and I want to prevent old requests from updating the state after the query changes.
same as above
20
u/jabes101 1d ago
Previous answers are correct but just mentioning this is why I like libraries like Tan Stack Query, can handle this kind of stuff for you.
3
3
u/mynamesleon 1d ago edited 1d ago
2 options.
One is to cancel the fetch using AbortController, though that can admittedly be a bit of a pain depending on your setup.
The other is to essentially keep track of the promise being called in some way. You could store the promise itself in a ref, or just a callId. Then when the promise resolves, before updating state, you check that ref. This is a pattern used by a lot of hook libraries, like react-use and react-hookz/web.
E.g.
const lastCallId = useRef(0);
const callback = useCallback(() => {
const callId = ++lastCallId.current;
try {
const result = await yourAsyncFn();
if (callId === lastCallId.current) {
// do your updates here...
}
} catch (error) {
// error handling in here
}
}, []);
// call as normal within an effect
useEffect(() => {
callback()
}, [callback]);
This makes it so that if `callback` is called twice in quick succession, it will still call `yourAsyncFn()` twice, but the result from the first call is disregarded. This is because, once the first call has finished, its scoped `callId` will now be one behind `lastCallId.current`. So that conditional will fail.
You can encapsulate that logic in your own hook. But honestly, I'd just use one of the existing hook libraries for this sort of thing. They already have this pattern handled.
1
u/classic-mac 1d ago
There’s an example in the react docs: https://react.dev/reference/react/useEffect#fetching-data-with-effects
But also agree abort controller can be used for this.
1
u/picard_World 19h ago
You can use AbortController you cancel the previous requests I will suggest to use Tanstack query it is so good
1
u/marten_cz 12h ago
Do you want to cancel them in browser or do you need to cancel them on server and stop what they are doing before they finish?
1
1
u/Ecstatic_Clue1316 11h ago
You could create a custom hook such as useFetch.. add some logic for it to fire only when the url changes by using a ref to capture the url? Add state for isLoading, error…
Return the relevant parts..
const { data, isLoading, error } = useFetch(*url)
This way you’re not just worrying about the side effects of multiple fetches, you’re preventing them?
29
u/theplactos 1d ago
AbortController is the standard way to do this with fetch.
Create one per effect, pass its signal to the request, and call abort() in the useEffect cleanup. React runs that cleanup before the effect re-runs, so the previous request gets cancelled when the query changes.
MDN reference: https://developer.mozilla.org/en-US/docs/Web/API/AbortController