You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/migrations/1.x-to-2.x.md
+71-3Lines changed: 71 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -271,7 +271,7 @@ We have also removed the `getType` export, which was used to extract a type stri
271
271
272
272
Previously, custom versions of React Redux's hooks (`useSelector`, `useDispatch`, and `useStore`) could be passed separately to `reactHooksModule`, usually to enable using a different context to the default `ReactReduxContext`.
273
273
274
-
The react hooks module requires all three of these hooks to be provided, and it became an easy mistake to only pass `useSelector` and `useDispatch`, without `useStore`.
274
+
In practicality, the react hooks module needs all three of these hooks to be provided, and it became an easy mistake to only pass `useSelector` and `useDispatch`, without `useStore`.
275
275
276
276
The module has now moved all three of these under the same configuration key, and will check that all three are provided if the key is present.
277
277
@@ -478,8 +478,8 @@ We've _wanted_ to include a way to define thunks directly inside of `createSlice
478
478
479
479
We've settled on these compromises:
480
480
481
-
- You can declare thunks inside of createSlice.reducers, by using a "creator callback" syntax for the reducers field that is similar to the build callback syntax in RTK Query's createApi (using typed functions to create fields in an object). Doing this does look a bit different than the existing "object" syntax for the reducers field, but is still fairly similar.
482
-
- You can customize some of the types for thunks inside of createSlice, but you cannot customize the state or dispatch types. If those are needed, you can manually do an as cast, like getState() as RootState.
481
+
- You can declare thunks inside of `createSlice.reducers`, by using a "creator callback" syntax for the `reducers` field that is similar to the `build` callback syntax in RTK Query's `createApi` (using typed functions to create fields in an object). Doing this does look a bit different than the existing "object" syntax for the `reducers` field, but is still fairly similar.
482
+
- You can customize _some_ of the types for thunks inside of `createSlice`, but you _cannot_ customize the `state` or `dispatch` types. If those are needed, you can manually do an `as` cast, like `getState() as RootState`.
483
483
- In order to create async thunks with `createSlice`, you specifically need to [set up a version that uses `createAsyncThunk`](../api/createSlice#createasyncthunk).
484
484
485
485
In practice, we hope these are reasonable tradeoffs. Creating thunks inside of `createSlice` has been widely asked for, so we think it's an API that will see usage. If the TS customization options are a limitation, you can still declare thunks outside of `createSlice` as always, and most async thunks don't need `dispatch` or `getState` - they just fetch data and return. And finally, setting up a custom `createSlice` allows you to opt into `createAsyncThunk` being included in your bundle size (though it may already be included if used directly or as part of RTK Query - in either of these cases there's no _additional_ bundle size).
@@ -628,8 +628,76 @@ We've updated RTK to depend on the final Immer 10.0 release.
628
628
629
629
## Recommendations
630
630
631
+
Based on changes in 2.0 and previous versions, there have been some shifts in thinking that are good to know about, if non-essential.
632
+
631
633
### Alternatives to `actionCreator.toString()`
632
634
635
+
As part of RTK's original API, action creators made with `createAction` have a custom `toString()` override that returns the action type.
636
+
637
+
This was primarily useful for the ([now removed](#object-syntax-for-createsliceextrareducers-and-createreducer-removed)) object syntax for `createReducer`:
[todoAdded]: (state, action) => {}, // toString called here, 'todos/todoAdded'
644
+
})
645
+
```
646
+
647
+
While this was convenient (and other libraries in the Redux ecosystem such as `redux-saga` and `redux-observable` have supported this to various capacities), it didn't play well with Typescript and was generally a bit too "magic".
648
+
649
+
```ts
650
+
const test =todoAdded.toString()
651
+
// ^? typed as string, rather than specific action type
652
+
```
653
+
654
+
Over time, the action creator also gained a static `type` property and `match` method which were more explicit and worked better with Typescript.
655
+
656
+
```ts
657
+
const test =todoAdded.type
658
+
// ^? 'todos/todoAdded'
659
+
660
+
// acts as a type predicate
661
+
if (todoAdded.match(unknownAction)) {
662
+
unknownAction.payload
663
+
// ^? now typed as PayloadAction<Todo>
664
+
}
665
+
```
666
+
667
+
For compatibility, this override is still in place, but we encourage considering using either of the static properties for more understandable code.
668
+
669
+
For example, with `redux-saga`:
670
+
671
+
```ts
672
+
// before (still works)
673
+
yieldtakeEvery(todoAdded, saga)
674
+
675
+
// consider
676
+
yieldtakeEvery(todoAdded.match, saga)
677
+
// or
678
+
yieldtakeEvery(todoAdded.type, saga)
679
+
```
680
+
681
+
With `redux-observable`:
682
+
683
+
```ts
684
+
// before (works in runtime, will not filter types properly)
0 commit comments