@@ -211,73 +211,6 @@ const onClick = () => {
211
211
}
212
212
```
213
213
214
- ## Examples
215
-
216
- Requesting a user by ID, with loading state, and only one request at a time:
217
-
218
- ``` js
219
- import { createAsyncThunk , createSlice , unwrapResult } from ' @reduxjs/toolkit'
220
- import { userAPI } from ' ./userAPI'
221
-
222
- const fetchUserById = createAsyncThunk (
223
- ' users/fetchByIdStatus' ,
224
- async (userId , { getState }) => {
225
- const { loading } = getState ().users
226
- if (loading !== ' idle' ) {
227
- return
228
- }
229
- const response = await userAPI .fetchById (userId)
230
- return response .data
231
- }
232
- )
233
-
234
- const usersSlice = createSlice ({
235
- name: ' users' ,
236
- initialState: {
237
- entities: [],
238
- loading: ' idle' ,
239
- error: null
240
- },
241
- reducers: {},
242
- extraReducers: {
243
- [fetchUserById .pending ]: (state , action ) => {
244
- if (state .loading === ' idle' ) {
245
- state .loading = ' pending'
246
- }
247
- },
248
- [fetchUserById .fulfilled ]: (state , action ) => {
249
- if (state .loading === ' pending' ) {
250
- state .loading = ' idle'
251
- state .push (action .payload )
252
- }
253
- },
254
- [fetchUserById .rejected ]: (state , action ) => {
255
- if (state .loading === ' pending' ) {
256
- state .loading = ' idle'
257
- state .error = action .error
258
- }
259
- }
260
- }
261
- })
262
-
263
- const UsersComponent = () => {
264
- const { users , loading , error } = useSelector (state => state .users )
265
- const dispatch = useDispatch ()
266
-
267
- const fetchOneUser = async userId => {
268
- try {
269
- const resultAction = dispatch (fetchUserById (userId))
270
- const user = unwrapResult (resultAction)
271
- showToast (' success' , ` Fetched ${ user .name } ` )
272
- } catch (err) {
273
- showToast (' error' , ` Fetch failed: ${ err .message } ` )
274
- }
275
- }
276
-
277
- // render UI here
278
- }
279
- ```
280
-
281
214
## Cancellation
282
215
283
216
If you want to cancel your running thunk before it has finished, you can use the ` abort ` method of the promise returned by ` dispatch(fetchUserById(userId)) ` .
@@ -287,19 +220,21 @@ A real-life example of that would look like this:
287
220
``` ts
288
221
function MyComponent(props : { userId: string }) {
289
222
React .useEffect (() => {
223
+ // Dispatching the thunk returns a promise
290
224
const promise = dispatch (fetchUserById (props .userId ))
291
225
return () => {
226
+ // `createAsyncThunk` attaches an `abort()` method to the promise
292
227
promise .abort ()
293
228
}
294
229
}, [props .userId ])
295
230
}
296
231
```
297
232
298
- After a thunk has been cancelled this way, it will dispatch (and return) a ` thunkName/rejected ` action with an ` AbortError ` on the ` error ` property. The thunk will not dispatch any further actions.
233
+ After a thunk has been cancelled this way, it will dispatch (and return) a ` " thunkName/rejected" ` action with an ` AbortError ` on the ` error ` property. The thunk will not dispatch any further actions.
299
234
300
235
Additionally, your ` payloadCreator ` can use the ` AbortSignal ` it is passed via ` thunkApi.signal ` to actually cancel a costly asynchronous action.
301
236
302
- The ` fetch ` api of modern browsers aleady comes with support for an ` AbortSignal ` :
237
+ The ` fetch ` api of modern browsers already comes with support for an ` AbortSignal ` :
303
238
304
239
``` ts
305
240
const fetchUserById = createAsyncThunk (
@@ -313,9 +248,9 @@ const fetchUserById = createAsyncThunk(
313
248
)
314
249
```
315
250
316
- But of course, you can also use it manually.
251
+ ### Checking Cancellation Status
317
252
318
- ### using ` signal.aborted `
253
+ ### Reading the Signal Value
319
254
320
255
You can use the ` signal.aborted ` property to regularly check if the thunk has been aborted and in that case stop costly long-running work:
321
256
@@ -338,7 +273,9 @@ const readStream = createAsyncThunk('readStream', async (stream: ReadableStream,
338
273
}
339
274
` ` `
340
275
341
- ### using ` signal .addEventListener (' abort' , () => ... )`
276
+ #### Listening for Abort Events
277
+
278
+ You can also call ` signal .addEventListener (' abort' , callback )` to have logic inside the thunk be notified when ` promise .abort ()` was called.
342
279
343
280
` ` ` ts
344
281
const readStream = createAsyncThunk (
@@ -357,3 +294,70 @@ const readStream = createAsyncThunk(
357
294
})
358
295
)
359
296
` ` `
297
+
298
+ ## Examples
299
+
300
+ Requesting a user by ID, with loading state, and only one request at a time:
301
+
302
+ ` ` ` js
303
+ import { createAsyncThunk , createSlice , unwrapResult } from ' @reduxjs/toolkit'
304
+ import { userAPI } from ' ./userAPI'
305
+
306
+ const fetchUserById = createAsyncThunk (
307
+ ' users/fetchByIdStatus' ,
308
+ async (userId , { getState }) => {
309
+ const { loading } = getState ().users
310
+ if (loading !== ' idle' ) {
311
+ return
312
+ }
313
+ const response = await userAPI .fetchById (userId )
314
+ return response .data
315
+ }
316
+ )
317
+
318
+ const usersSlice = createSlice ({
319
+ name: ' users' ,
320
+ initialState: {
321
+ entities: [],
322
+ loading: ' idle' ,
323
+ error: null
324
+ },
325
+ reducers: {},
326
+ extraReducers: {
327
+ [fetchUserById .pending ]: (state , action ) => {
328
+ if (state .loading === ' idle' ) {
329
+ state .loading = ' pending'
330
+ }
331
+ },
332
+ [fetchUserById .fulfilled ]: (state , action ) => {
333
+ if (state .loading === ' pending' ) {
334
+ state .loading = ' idle'
335
+ state .push (action .payload )
336
+ }
337
+ },
338
+ [fetchUserById .rejected ]: (state , action ) => {
339
+ if (state .loading === ' pending' ) {
340
+ state .loading = ' idle'
341
+ state .error = action .error
342
+ }
343
+ }
344
+ }
345
+ })
346
+
347
+ const UsersComponent = () => {
348
+ const { users, loading, error } = useSelector (state => state .users )
349
+ const dispatch = useDispatch ()
350
+
351
+ const fetchOneUser = async userId => {
352
+ try {
353
+ const resultAction = dispatch (fetchUserById (userId ))
354
+ const user = unwrapResult (resultAction )
355
+ showToast (' success' , ` Fetched ${user .name } ` )
356
+ } catch (err ) {
357
+ showToast (' error' , ` Fetch failed: ${err .message } ` )
358
+ }
359
+ }
360
+
361
+ // render UI here
362
+ }
363
+ ` ` `
0 commit comments