|
1 | 1 | --- |
2 | 2 | id: usage-with-typescript |
3 | | -title: Usage with TypeScript |
| 3 | +title: Typing connect with TypeScript |
4 | 4 | hide_title: true |
5 | | -sidebar_label: Usage with TypeScript |
6 | | -description: 'Usage > TypeScript: how to correctly type React Redux APIs' |
| 5 | +sidebar_label: 'Connect: Usage with TypeScript' |
| 6 | +description: 'Usage > TypeScript: how to type the legacy connect API' |
7 | 7 | --- |
8 | 8 |
|
9 | 9 | |
10 | 10 |
|
11 | | -# Usage with TypeScript |
| 11 | +# Typing `connect` with TypeScript |
12 | 12 |
|
13 | | -As of React-Redux v8, React-Redux is fully written in TypeScript, and the types are included in the published package. The types also export some helpers to make it easier to write typesafe interfaces between your Redux store and your React components. |
| 13 | +:::warning Deprecated |
14 | 14 |
|
15 | | -:::info |
16 | | - |
17 | | -The recently updated `@types/react@18` major version has changed component definitions to remove having `children` as a prop by default. This causes errors if you have multiple copies of `@types/react` in your project. To fix this, tell your package manager to resolve `@types/react` to a single version. Details: |
18 | | - |
19 | | -https://github.com/facebook/react/issues/24304#issuecomment-1094565891 |
| 15 | +`connect` is marked as deprecated as of React-Redux 9.3.0. It still works, and we do not intend to remove it, but [**we recommend using the hooks API instead**](../api/hooks.md). The hooks are also much simpler to type. For the standard TypeScript setup with `RootState`, `AppDispatch`, and pre-typed `useAppSelector` / `useAppDispatch` hooks, see [**Usage with TypeScript**](/usage/usage-with-typescript) in the Redux docs. |
20 | 16 |
|
21 | 17 | ::: |
22 | 18 |
|
23 | | -## Standard Redux Toolkit Project Setup with TypeScript |
24 | | - |
25 | | -We assume that a typical Redux project is using Redux Toolkit and React Redux together. |
26 | | - |
27 | | -[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. |
28 | | - |
29 | | -The [Redux+TS template for Vite](https://github.com/reduxjs/redux-templates/tree/master/packages/vite-template-redux) comes with a working example of these patterns already configured. |
30 | | - |
31 | | -### Define Root State and Dispatch Types |
32 | | - |
33 | | -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. |
34 | | - |
35 | | -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. |
36 | | - |
37 | | -```ts title="app/store.ts" |
38 | | -import { configureStore } from '@reduxjs/toolkit' |
39 | | -// ... |
40 | | - |
41 | | -const store = configureStore({ |
42 | | - reducer: { |
43 | | - posts: postsReducer, |
44 | | - comments: commentsReducer, |
45 | | - users: usersReducer, |
46 | | - }, |
47 | | -}) |
48 | | - |
49 | | -// highlight-start |
50 | | -// Infer the `RootState` and `AppDispatch` types from the store itself |
51 | | -export type RootState = ReturnType<typeof store.getState> |
52 | | -// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState} |
53 | | -export type AppDispatch = typeof store.dispatch |
54 | | -// highlight-end |
55 | | -``` |
56 | | -
|
57 | | -### Define Typed Hooks |
58 | | -
|
59 | | -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: |
60 | | -
|
61 | | -- For `useSelector`, it saves you the need to type `(state: RootState)` every time |
62 | | -- 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. |
63 | | -
|
64 | | -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. |
65 | | -
|
66 | | -#### `.withTypes()` |
67 | | -
|
68 | | -Previously, the approach for "pre-typing" hooks with your app setting was a little varied. The result would look something like the snippet below: |
69 | | -
|
70 | | -```ts title="app/hooks.ts" |
71 | | -import type { TypedUseSelectorHook } from 'react-redux' |
72 | | -import { useDispatch, useSelector, useStore } from 'react-redux' |
73 | | -import type { AppDispatch, AppStore, RootState } from './store' |
74 | | - |
75 | | -// highlight-start |
76 | | -// Use throughout your app instead of plain `useDispatch` and `useSelector` |
77 | | -export const useAppDispatch: () => AppDispatch = useDispatch |
78 | | -export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector |
79 | | -export const useAppStore: () => AppStore = useStore |
80 | | -// highlight-end |
81 | | -``` |
82 | | - |
83 | | -React Redux v9.1.0 adds a new `.withTypes` method to each of these hooks, analogous to the [`.withTypes`](https://redux-toolkit.js.org/usage/usage-with-typescript#defining-a-pre-typed-createasyncthunk) method found on Redux Toolkit's `createAsyncThunk`. |
84 | | - |
85 | | -The setup now becomes: |
86 | | - |
87 | | -```ts title="app/hooks.ts" |
88 | | -import { useDispatch, useSelector, useStore } from 'react-redux' |
89 | | -import type { AppDispatch, AppStore, RootState } from './store' |
90 | | - |
91 | | -// highlight-start |
92 | | -// Use throughout your app instead of plain `useDispatch` and `useSelector` |
93 | | -export const useAppDispatch = useDispatch.withTypes<AppDispatch>() |
94 | | -export const useAppSelector = useSelector.withTypes<RootState>() |
95 | | -export const useAppStore = useStore.withTypes<AppStore>() |
96 | | -// highlight-end |
97 | | -``` |
98 | | - |
99 | | -## Typing Hooks Manually |
100 | | - |
101 | | -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. |
102 | | - |
103 | | -### Typing the `useSelector` hook |
104 | | - |
105 | | -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: |
106 | | - |
107 | | -```ts |
108 | | -interface RootState { |
109 | | - isOn: boolean |
110 | | -} |
111 | | - |
112 | | -// TS infers type: (state: RootState) => boolean |
113 | | -const selectIsOn = (state: RootState) => state.isOn |
114 | | - |
115 | | -// TS infers `isOn` is boolean |
116 | | -const isOn = useSelector(selectIsOn) |
117 | | -``` |
118 | | - |
119 | | -This can also be done inline as well: |
120 | | - |
121 | | -```ts |
122 | | -const isOn = useSelector((state: RootState) => state.isOn) |
123 | | -``` |
124 | | - |
125 | | -### Typing the `useDispatch` hook |
126 | | - |
127 | | -By default, the return value of `useDispatch` is the standard `Dispatch` type defined by the Redux core types, so no declarations are needed: |
128 | | - |
129 | | -```ts |
130 | | -const dispatch = useDispatch() |
131 | | -``` |
132 | | - |
133 | | -If you have a customized version of the `Dispatch` type, you may use that type explicitly: |
134 | | - |
135 | | -```ts |
136 | | -// store.ts |
137 | | -export type AppDispatch = typeof store.dispatch |
138 | | - |
139 | | -// MyComponent.tsx |
140 | | -const dispatch: AppDispatch = useDispatch() |
141 | | -``` |
| 19 | +React-Redux is written in TypeScript, and the types are included in the published package. This page covers the patterns for typing the `connect` higher-order component. |
142 | 20 |
|
143 | 21 | ## Typing the `connect` higher order component |
144 | 22 |
|
@@ -271,15 +149,12 @@ However, inferring the type of `mapDispatch` this way will break if it is define |
271 | 149 |
|
272 | 150 | ## Recommendations |
273 | 151 |
|
274 | | -The hooks API is generally simpler to use with static types. **If you're looking for the easiest solution for using static types with React-Redux, use the hooks API.** |
275 | | -
|
276 | 152 | If you're using `connect`, **we recommend using the `ConnectedProps<T>` approach for inferring the props from Redux**, as that requires the fewest explicit type declarations. |
277 | 153 |
|
278 | | -## Resources |
| 154 | +If you're able to migrate, the hooks API is simpler to type. See [Migrating to Modern Redux: Modernizing React Components](/usage/migrating-to-modern-redux#modernizing-react-components-with-react-redux) for how to convert `connect` usage to hooks. |
279 | 155 |
|
280 | | -For additional information, see these additional resources: |
| 156 | +## Resources |
281 | 157 |
|
282 | | -- [Redux docs: Usage with TypeScript](/usage/usage-with-typescript): Examples of how to use Redux Toolkit, the Redux core, and React Redux with TypeScript |
| 158 | +- [Redux docs: Usage with TypeScript](/usage/usage-with-typescript): the standard TypeScript setup for Redux Toolkit and the React-Redux hooks |
283 | 159 | - [Redux docs: Quick Start](/tutorials/quick-start): shows how to use RTK and the React-Redux hooks API with TypeScript |
284 | | -- [React+TypeScript Cheatsheet](https://github.com/typescript-cheatsheets/react-typescript-cheatsheet): a comprehensive guide to using React with TypeScript |
285 | | -- [React + Redux in TypeScript Guide](https://github.com/piotrwitek/react-redux-typescript-guide): extensive information on patterns for using React and Redux with TypeScript |
| 160 | +- [React+TypeScript Cheatsheet](https://github.com/typescript-cheatsheets/react): a comprehensive guide to using React with TypeScript |
0 commit comments