redux-toolkit icon indicating copy to clipboard operation
redux-toolkit copied to clipboard

CancelToken from axios is deprecated

Open tony-ist opened this issue 3 years ago • 9 comments

CancelToken from axios is deprecated, so I suggest updating the documentation to use AbortController instead.

tony-ist avatar Mar 20 '22 00:03 tony-ist

createAsyncThunk already supports AbortController natively - this example is there to show that also other mechanisms by external libraries can be used. Do you know of any other library that uses something else than AbortController we can use instead of axios then?

phryneas avatar Mar 20 '22 07:03 phryneas

@phryneas No, I only use axios and fetch. But I struggle to find documentation on how to use AbortController with createAsyncThunk. I mean, we have thunkApi which has signal, but where do I find the instance of AbortController to call .abort()?

tony-ist avatar Mar 20 '22 10:03 tony-ist

You don't need any AbortController instance, you just call abort on the thunk.

const dispatchedThunk = dispatch(myThunk())

dispatchedThunk.abort()

phryneas avatar Mar 20 '22 11:03 phryneas

You don't need any AbortController instance, you just call abort on the thunk.

But that doesn't tell axios to cancel the request. If you look at the actual network request, it's not cancelled.

johnflux avatar Jul 04 '22 00:07 johnflux

@johnflux if you don't pass the signal in some way to axios, that will do nothing, correct. That's your responsibility.

phryneas avatar Jul 04 '22 06:07 phryneas

@johnflux if you don't pass the signal in some way to axios, that will do nothing, correct. That's your responsibility.

Yeah I'm just surprised that I don't see good examples for it. I found out how:

const fetchUserByIdThunk = createAsyncThunk(
  'users/fetchById',
  async (userId: string, { signal }) => {
    const controller = new AbortController();
    signal.addEventListener('abort', () => controller.abort())
    const response = await axios.get(`https://reqres.in/api/users/${userId}`, {
      signal: controller.signal,
    })
    return response.data
  }
)

Then when you call it:

useEffect(() = {
  const p = dispatch(fetchUserByIdThunk({userId}));
  return () = p.abort();
}, [userId]);

johnflux avatar Jul 04 '22 07:07 johnflux

You already have a signal, why do you create another?

const fetchUserByIdThunk = createAsyncThunk(
  'users/fetchById',
  async (userId: string, { signal }) => {
    const response = await axios.get(`https://reqres.in/api/users/${userId}`, {
      signal,
    })
    return response.data
  }
)

phryneas avatar Jul 04 '22 07:07 phryneas

Generally, I'd welcome a docs PR for this, but if possible, please use fetch, not axios in the example. There is almost no good reason (except niche stuff like tracking file upload progress) to use axios nowadays and I don't really want to steer people to waste 6kb of bundle size.

phryneas avatar Jul 04 '22 07:07 phryneas

I had no idea that you could use the same signal. I haven't seen that documented anywhere, but that's cool.

For the docs, how about both please?

johnflux avatar Jul 04 '22 07:07 johnflux