Skip to content

Commit 8fec378

Browse files
authored
Merge pull request reduxjs#1259 from Shrugsy/docs/show-unwrap-property-usage
📝 Document .unwrap() usage for createAsyncThunk
2 parents 6d5286a + ed29a85 commit 8fec378

File tree

1 file changed

+61
-9
lines changed

1 file changed

+61
-9
lines changed

docs/api/createAsyncThunk.mdx

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -246,25 +246,78 @@ const onClick = () => {
246246

247247
The thunks generated by `createAsyncThunk` **will always return a resolved promise** with either the `fulfilled` action object or `rejected` action object inside, as appropriate.
248248

249-
The calling logic may wish to treat these actions as if they were the original promise contents. Redux Toolkit exports an `unwrapResult` function that can be used to extract the `payload` of a `fulfilled` action or to throw either the `error` or, if available, `payload` created by `rejectWithValue` from a `rejected` action:
249+
The calling logic may wish to treat these actions as if they were the original promise contents. The promise returned by the dispatched thunk has an `unwrap` property which can be called to extract the `payload` of a `fulfilled` action or to throw either the `error` or, if available, `payload` created by `rejectWithValue` from a `rejected` action:
250250

251-
```js
251+
```ts no-transpile
252+
// in the component
253+
254+
const onClick = () => {
255+
dispatch(fetchUserById(userId))
256+
.unwrap()
257+
.then((originalPromiseResult) => {
258+
// handle result here
259+
})
260+
.catch((rejectedValueOrSerializedError) => {
261+
// handle error here
262+
})
263+
}
264+
```
265+
266+
Or with async/await syntax:
267+
268+
```ts no-transpile
269+
// in the component
270+
271+
const onClick = async () => {
272+
try {
273+
const originalPromiseResult = await dispatch(fetchUserById(userId)).unwrap()
274+
// handle result here
275+
} catch (rejectedValueOrSerializedError) {
276+
// handle error here
277+
}
278+
}
279+
```
280+
281+
Using the attached `.unwrap()` property is preferred in most cases, however Redux Toolkit also exports an `unwrapResult` function that can be used for a similar purpose:
282+
283+
```ts no-transpile
252284
import { unwrapResult } from '@reduxjs/toolkit'
253285

254286
// in the component
255287
const onClick = () => {
256288
dispatch(fetchUserById(userId))
257289
.then(unwrapResult)
258-
.then((originalPromiseResult) => {})
259-
.catch((rejectedValueOrSerializedError) => {})
290+
.then((originalPromiseResult) => {
291+
// handle result here
292+
})
293+
.catch((rejectedValueOrSerializedError) => {
294+
// handle result here
295+
})
296+
}
297+
```
298+
299+
Or with async/await syntax:
300+
301+
```ts no-transpile
302+
import { unwrapResult } from '@reduxjs/toolkit'
303+
304+
// in the component
305+
const onClick = async () => {
306+
try {
307+
const resultAction = await dispatch(fetchUserById(userId))
308+
const originalPromiseResult = unwrapResult(resultAction)
309+
// handle result here
310+
} catch (rejectedValueOrSerializedError) {
311+
// handle error here
312+
}
260313
}
261314
```
262315

263316
### Checking Errors After Dispatching
264317

265318
Note that this means **a failed request or error in a thunk will _never_ return a _rejected_ promise**. We assume that any failure is more of a handled error than an unhandled exception at this point. This is due to the fact that we want to prevent uncaught promise rejections for those who do not use the result of `dispatch`.
266319

267-
If your component needs to know if the request failed, use `unwrapResult` and handle the re-thrown error accordingly.
320+
If your component needs to know if the request failed, use `.unwrap` or `unwrapResult` and handle the re-thrown error accordingly.
268321

269322
## Handling Thunk Errors
270323

@@ -449,7 +502,7 @@ const fetchUserById = createAsyncThunk(
449502
- Requesting a user by ID, with loading state, and only one request at a time:
450503

451504
```js
452-
import { createAsyncThunk, createSlice, unwrapResult } from '@reduxjs/toolkit'
505+
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
453506
import { userAPI } from './userAPI'
454507

455508
const fetchUserById = createAsyncThunk(
@@ -512,8 +565,7 @@ const UsersComponent = () => {
512565

513566
const fetchOneUser = async (userId) => {
514567
try {
515-
const resultAction = await dispatch(fetchUserById(userId))
516-
const user = unwrapResult(resultAction)
568+
const user = await dispatch(fetchUserById(userId)).unwrap()
517569
showToast('success', `Fetched ${user.name}`)
518570
} catch (err) {
519571
showToast('error', `Fetch failed: ${err.message}`)
@@ -545,7 +597,7 @@ export declare const userAPI: {
545597
}
546598

547599
// file: user/slice.ts
548-
import { createAsyncThunk, createSlice, unwrapResult } from '@reduxjs/toolkit'
600+
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
549601
import { userAPI } from './userAPI'
550602
import { AxiosError } from 'axios'
551603

0 commit comments

Comments
 (0)