I believe that the currentuseCancelToken is faulty in some cases.
Currently: it exports a newCancelToken method that generates a new cancel token on each call of this function, and saves the latest cancel token source object on a ref. This will cause a problem in a component that does 2 different api calls with 2 different tokens. This hook will only cancel the latest of them on unmount.
When clicking unmount A quickly (before allowing the api calls to finish), Expected result: logs to console "canceled 1", "canceled 2", "canceled 3" (order doesn't matter) with no warnings Current result: it logs canceled 3, Done 1, Done 2, and spits out the setState warning
The suggested implementation is to create only one cancel token per component and cancel all api calls on unmounting:
Also, as an addition to the article. This hook only deals with cancelling api calls on unmounting. Another use case for cancelling is cancelling api calls on dependency changes. For example:
...
const userId = props.userId;
useEffect(() => {
// load something based on userId
}, [userId]);
If the userId changes quickly, we might want to cancel the old ongoing request. I believe it is better to create the CancelToken/AbortController locally inside the effect and cancel/abort in the return function of the effect without the usage of extra hooks. Do you have another suggestion or pattern for doing this?
Thanks for the thorough reply and bringing up the issue about creating multiple cancel tokens within the same component. It's true that if you're going to be using it in several different calls like that you'd either want to just create one cancel token and export it directly (like you suggested) or create the cancel token once in the calling component (and storing it in a ref if it may rerender). I think your approach is the simplest as long as a function isn't specifically needed for some reason. I'll add a little note to the article pointing to your comment π
As for your other point about the use cases of the hook. Yes, this is only about unmounting. There are maaaany cases where you may want to cancel a request, which may not even require a dependency change (e.g. network issues and race conditions). For those cases I've typically just handled them manually like you suggested, as they tend to be more difficult to easily abstract than the classic "if component unmounts." If you come up with a better way though let me know!
Hi, thanks for your article.
I believe that the current
useCancelToken
is faulty in some cases.Currently: it exports a
newCancelToken
method that generates a new cancel token on each call of this function, and saves the latest cancel token source object on a ref. This will cause a problem in a component that does 2 different api calls with 2 different tokens. This hook will only cancel the latest of them on unmount.i.e., a component that looks like this
I've reproduced this bug in the code in this repo here: github.com/MostafaOmar98/use-cance...
When clicking
unmount A
quickly (before allowing the api calls to finish),Expected result: logs to console "canceled 1", "canceled 2", "canceled 3" (order doesn't matter) with no warnings
Current result: it logs
canceled 3
,Done 1
,Done 2
, and spits out thesetState
warningThe suggested implementation is to create only one cancel token per component and cancel all api calls on unmounting:
Also, as an addition to the article. This hook only deals with cancelling api calls on unmounting. Another use case for cancelling is cancelling api calls on dependency changes. For example:
If the userId changes quickly, we might want to cancel the old ongoing request. I believe it is better to create the CancelToken/AbortController locally inside the effect and cancel/abort in the return function of the effect without the usage of extra hooks. Do you have another suggestion or pattern for doing this?
Thanks!
Hey Mostafa!
Thanks for the thorough reply and bringing up the issue about creating multiple cancel tokens within the same component. It's true that if you're going to be using it in several different calls like that you'd either want to just create one cancel token and export it directly (like you suggested) or create the cancel token once in the calling component (and storing it in a ref if it may rerender). I think your approach is the simplest as long as a function isn't specifically needed for some reason. I'll add a little note to the article pointing to your comment π
As for your other point about the use cases of the hook. Yes, this is only about unmounting. There are maaaany cases where you may want to cancel a request, which may not even require a dependency change (e.g. network issues and race conditions). For those cases I've typically just handled them manually like you suggested, as they tend to be more difficult to easily abstract than the classic "if component unmounts." If you come up with a better way though let me know!
Have a great one!
Thanks for the reply and the feature on the article! Have a great one too!