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/using-react-redux/usage-with-typescript.md
+122-93
Original file line number
Diff line number
Diff line change
@@ -7,27 +7,71 @@ sidebar_label: Usage with TypeScript
7
7
8
8
# Usage with TypeScript
9
9
10
-
React-Redux itself is currently written in plain JavaScript. However, it works well with static type systems such as TypeScript and Flow.
10
+
React-Redux itself is currently written in plain JavaScript. However, it works well with static type systems such as TypeScript.
11
11
12
12
React-Redux doesn't ship with its own type definitions. If you are using TypeScript you should install the [`@types/react-redux` type definitions](https://npm.im/@types/react-redux) from NPM. In addition to typing the library functions, the types also export some helpers to make it easier to write typesafe interfaces between your Redux store and your React components.
13
13
14
-
## Defining the Root State Type
15
14
16
-
Both `mapState` and `useSelector` depend on declaring the type of the complete Redux store state value. While this type could be written by hand, the easiest way to define it is to have TypeScript infer it based on what your root reducer function returns. This way, the type is automatically updated as the reducer functions are modified.
15
+
## Standard Redux Toolkit Project Setup with TypeScript
17
16
18
-
```ts
19
-
// rootReducer.ts
20
-
exportconst rootReducer =combineReducers({
21
-
posts: postsReducer,
22
-
comments: commentsReducer,
23
-
users: usersReducer,
17
+
We assume that a typical Redux project is using Redux Toolkit and React Redux together.
18
+
19
+
[Redux Toolkit](https://redux-toolkit.js.org) (RTK) is the standard approach for writing modern Redux logic. RTK is already written in TypeScript, and its API is designed to provide a good experience for TypeScript usage.
20
+
21
+
The [Redux+TS template for Create-React-App](https://github.com/reduxjs/cra-template-redux-typescript) comes with a working example of these patterns already configured.
22
+
23
+
### Define Root State and Dispatch Types
24
+
25
+
Using [configureStore](https://redux-toolkit.js.org/api/configureStore) should not need any additional typings. You will, however, want to extract the `RootState` type and the `Dispatch` type so that they can be referenced as needed. Inferring these types from the store itself means that they correctly update as you add more state slices or modify middleware settings.
26
+
27
+
Since those are types, it's safe to export them directly from your store setup file such as `app/store.ts` and import them directly into other files.
While it's possible to import the `RootState` and `AppDispatch` types into each component, it's better to **create pre-typed versions of the `useDispatch` and `useSelector` hooks for usage in your application**. This is important for a couple reasons:
52
+
53
+
- For `useSelector`, it saves you the need to type `(state:RootState)` every time
54
+
- For `useDispatch`, the default `Dispatch` type does not know about thunks or other middleware. In order to correctly dispatch thunks, you need to use the specific customized `AppDispatch` type from the store that includes the thunk middleware types, and use that with `useDispatch`. Adding a pre-typed `useDispatch` hook keeps you from forgetting to import `AppDispatch` where it's needed.
55
+
56
+
Since these are actual variables, not types, it's important to define them in a separate file such as `app/hooks.ts`, not the store setup file. This allows you to import them into any component file that needs to use the hooks, and avoids potential circular import dependency issues.
We recommend using the pre-typed `useAppSelector` and `useAppDispatch` hooks shown above. If you prefer not to use those, here is how to type the hooks by themselves.
73
+
74
+
### Typing the `useSelector` hook
31
75
32
76
When writing selector functions for use with `useSelector`, you should explicitly define the type of the `state` parameter. TS should be able to then infer the return type of the selector, which will be reused as the return type of the `useSelector` hook:
If you want to avoid repeating the `state` type declaration, you can define a typed `useSelector` hook using a helper type exported by `@types/react-redux`:
const isOn =useTypedSelector((state) =>state.isOn)
93
+
const isOn =useSelector( (state:RootState) =>state.isOn)
62
94
```
63
95
64
-
## Typing the `useDispatch` hook
96
+
97
+
### Typing the `useDispatch` hook
65
98
66
99
By default, the return value of `useDispatch` is the standard `Dispatch` type defined by the Redux core types, so no declarations are needed:
67
100
@@ -79,14 +112,72 @@ export type AppDispatch = typeof store.dispatch
79
112
const dispatch:AppDispatch=useDispatch()
80
113
```
81
114
82
-
You may also find it to be more convenient to export a hook like `useAppDispatch` shown below, then using it wherever you'd call `useDispatch`:
115
+
116
+
## Typing the `connect` higher order component
117
+
118
+
119
+
### Inferring The Connected Props Automatically
120
+
121
+
`connect` consists of two functions that are called sequentially. The first function accepts `mapState` and `mapDispatch` as arguments, and returns a second function. The second function accepts the component to be wrapped, and returns a new wrapper component that passes down the props from `mapState` and `mapDispatch`. Normally, both functions are called together, like `connect(mapState, mapDispatch)(MyComponent)`.
122
+
123
+
As of v7.1.2, the `@types/react-redux` package exposes a helper type, `ConnectedProps`, that can extract the return types of `mapStateToProps` and `mapDispatchToProps` from the first function. This means that if you split the `connect` call into two steps, all of the "props from Redux" can be inferred automatically without having to write them by hand. While this approach may feel unusual if you've been using React-Redux for a while, it does simplify the type declarations considerably.
83
124
84
125
```ts
85
-
exporttypeAppDispatch=typeofstore.dispatch
86
-
exportconst useAppDispatch = () =>useDispatch<AppDispatch>() // Export a hook that can be reused to resolve types
However, inferring the type of `mapDispatch` this way will break if it is defined as an object and also refers to thunks.
153
244
154
-
### Inferring The Connected Props Automatically
155
-
156
-
`connect` consists of two functions that are called sequentially. The first function accepts `mapState` and `mapDispatch` as arguments, and returns a second function. The second function accepts the component to be wrapped, and returns a new wrapper component that passes down the props from `mapState` and `mapDispatch`. Normally, both functions are called together, like `connect(mapState, mapDispatch)(MyComponent)`.
157
-
158
-
As of v7.1.2, the `@types/react-redux` package exposes a helper type, `ConnectedProps`, that can extract the return types of `mapStateToProps` and `mapDispatchToProps` from the first function. This means that if you split the `connect` call into two steps, all of the "props from Redux" can be inferred automatically without having to write them by hand. While this approach may feel unusual if you've been using React-Redux for a while, it does simplify the type declarations considerably.
0 commit comments