Skip to content

Commit b9616df

Browse files
committed
Reorder cancellation content and improve wording
1 parent 491a122 commit b9616df

File tree

1 file changed

+76
-72
lines changed

1 file changed

+76
-72
lines changed

docs/api/createAsyncThunk.md

Lines changed: 76 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -211,73 +211,6 @@ const onClick = () => {
211211
}
212212
```
213213

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-
281214
## Cancellation
282215

283216
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:
287220
```ts
288221
function MyComponent(props: { userId: string }) {
289222
React.useEffect(() => {
223+
// Dispatching the thunk returns a promise
290224
const promise = dispatch(fetchUserById(props.userId))
291225
return () => {
226+
// `createAsyncThunk` attaches an `abort()` method to the promise
292227
promise.abort()
293228
}
294229
}, [props.userId])
295230
}
296231
```
297232

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.
299234

300235
Additionally, your `payloadCreator` can use the `AbortSignal` it is passed via `thunkApi.signal` to actually cancel a costly asynchronous action.
301236

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`:
303238

304239
```ts
305240
const fetchUserById = createAsyncThunk(
@@ -313,9 +248,9 @@ const fetchUserById = createAsyncThunk(
313248
)
314249
```
315250

316-
But of course, you can also use it manually.
251+
### Checking Cancellation Status
317252

318-
### using `signal.aborted`
253+
### Reading the Signal Value
319254

320255
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:
321256

@@ -338,7 +273,9 @@ const readStream = createAsyncThunk('readStream', async (stream: ReadableStream,
338273
}
339274
```
340275
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.
342279
343280
```ts
344281
const readStream = createAsyncThunk(
@@ -357,3 +294,70 @@ const readStream = createAsyncThunk(
357294
})
358295
)
359296
```
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

Comments
 (0)