diff --git a/docs/api/createAsyncThunk.mdx b/docs/api/createAsyncThunk.mdx index c44803fda0..e837148300 100644 --- a/docs/api/createAsyncThunk.mdx +++ b/docs/api/createAsyncThunk.mdx @@ -527,7 +527,7 @@ If a thunk was cancelled, the result of the promise will be a `rejected` action So if you wanted to test that a thunk was cancelled before executing, you can do the following: ```ts no-transpile -import { createAsyncThunk, isRejected } from '@reduxjs/toolkit' +import { createAsyncThunk } from '@reduxjs/toolkit' test('this thunk should always be skipped', async () => { const thunk = createAsyncThunk( diff --git a/examples/query/react/kitchen-sink/src/features/auth/authSlice.ts b/examples/query/react/kitchen-sink/src/features/auth/authSlice.ts index 392d8bcd94..07596a6f20 100644 --- a/examples/query/react/kitchen-sink/src/features/auth/authSlice.ts +++ b/examples/query/react/kitchen-sink/src/features/auth/authSlice.ts @@ -24,6 +24,7 @@ const slice = createSlice({ console.log('fulfilled', action) state.user = action.payload.user state.token = action.payload.token + state.isAuthenticated = true }) .addMatcher(postsApi.endpoints.login.matchRejected, (state, action) => { console.log('rejected', action) diff --git a/packages/toolkit/src/createAsyncThunk.ts b/packages/toolkit/src/createAsyncThunk.ts index f75653bda9..ef4f5f1977 100644 --- a/packages/toolkit/src/createAsyncThunk.ts +++ b/packages/toolkit/src/createAsyncThunk.ts @@ -577,6 +577,7 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { : nanoid() const abortController = new AbortController() + let abortHandler: (() => void) | undefined let abortReason: string | undefined function abort(reason?: string) { @@ -600,14 +601,15 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { } } - const abortedPromise = new Promise((_, reject) => - abortController.signal.addEventListener('abort', () => + const abortedPromise = new Promise((_, reject) => { + abortHandler = () => { reject({ name: 'AbortError', message: abortReason || 'Aborted', }) - ) - ) + } + abortController.signal.addEventListener('abort', abortHandler) + }) dispatch( pending( requestId, @@ -653,6 +655,10 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { err instanceof RejectWithValue ? rejected(null, requestId, arg, err.payload, err.meta) : rejected(err as any, requestId, arg) + } finally { + if (abortHandler) { + abortController.signal.removeEventListener('abort', abortHandler) + } } // We dispatch the result action _after_ the catch, to avoid having any errors // here get swallowed by the try/catch block,