Skip to content

Commit cccf40a

Browse files
authored
Merge pull request #4308 from aryaemami59/TypedUseSelectorHook-to-withTypes
Update React Redux dependency to v9, and update docs to use `.withTypes`
2 parents 1afcdd4 + 5a01e09 commit cccf40a

File tree

13 files changed

+136
-71
lines changed

13 files changed

+136
-71
lines changed

docs/tutorials/typescript.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,12 @@ Since these are actual variables, not types, it's important to define them in a
7676
7777
```ts title="app/hooks.ts"
7878
import { useDispatch, useSelector } from 'react-redux'
79-
import type { TypedUseSelectorHook } from 'react-redux'
8079
import type { RootState, AppDispatch } from './store'
8180

8281
// highlight-start
8382
// Use throughout your app instead of plain `useDispatch` and `useSelector`
84-
export const useAppDispatch: () => AppDispatch = useDispatch
85-
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
83+
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
84+
export const useAppSelector = useSelector.withTypes<RootState>()
8685
// highlight-end
8786
```
8887

docs/usage/migrating-rtk-2.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,6 @@ React Redux supports creating `hooks` (and `connect`) with a [custom context](ht
448448
import { createContext } from 'react'
449449
import {
450450
ReactReduxContextValue,
451-
TypedUseSelectorHook,
452451
createDispatchHook,
453452
createSelectorHook,
454453
createStoreHook,
@@ -458,10 +457,9 @@ import { AppStore, RootState, AppDispatch } from './store'
458457
// highlight-next-line
459458
const context = createContext<ReactReduxContextValue>(null as any)
460459

461-
export const useStore: () => AppStore = createStoreHook(context)
462-
export const useDispatch: () => AppDispatch = createDispatchHook(context)
463-
export const useSelector: TypedUseSelectorHook<RootState> =
464-
createSelectorHook(context)
460+
export const useStore = createStoreHook(context).withTypes<AppStore>()
461+
export const useDispatch = createDispatchHook(context).withTypes<AppDispatch>()
462+
export const useSelector = createSelectorHook(context).withTypes<RootState>()
465463
```
466464

467465
In v9, the types now match the runtime behaviour. The context is typed to hold `ReactReduxContextValue | null`, and the hooks know that if they receive `null` they'll throw an error so it doesn't affect the return type.
@@ -472,7 +470,6 @@ The above example now becomes:
472470
import { createContext } from 'react'
473471
import {
474472
ReactReduxContextValue,
475-
TypedUseSelectorHook,
476473
createDispatchHook,
477474
createSelectorHook,
478475
createStoreHook,
@@ -482,10 +479,9 @@ import { AppStore, RootState, AppDispatch } from './store'
482479
// highlight-next-line
483480
const context = createContext<ReactReduxContextValue | null>(null)
484481

485-
export const useStore: () => AppStore = createStoreHook(context)
486-
export const useDispatch: () => AppDispatch = createDispatchHook(context)
487-
export const useSelector: TypedUseSelectorHook<RootState> =
488-
createSelectorHook(context)
482+
export const useStore = createStoreHook(context).withTypes<AppStore>()
483+
export const useDispatch = createDispatchHook(context).withTypes<AppDispatch>()
484+
export const useSelector = createSelectorHook(context).withTypes<RootState>()
489485
```
490486

491487
</div>

docs/usage/migrating-to-modern-redux.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,13 +1110,13 @@ Per [our standard TypeScript setup and usage guidelines](../tutorials/typescript
11101110
First, set up the hooks:
11111111

11121112
```ts no-transpile title="src/app/hooks.ts"
1113-
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
1113+
import { useDispatch, useSelector } from 'react-redux'
11141114
import type { RootState, AppDispatch } from './store'
11151115

11161116
// highlight-start
11171117
// Use throughout your app instead of plain `useDispatch` and `useSelector`
1118-
export const useAppDispatch: () => AppDispatch = useDispatch
1119-
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
1118+
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
1119+
export const useAppSelector = useSelector.withTypes<RootState>()
11201120
// highlight-end
11211121
```
11221122

docs/usage/nextjs.mdx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,13 @@ export type AppDispatch = AppStore['dispatch']
135135

136136
// file: lib/hooks.ts
137137
import { useDispatch, useSelector, useStore } from 'react-redux'
138-
import type { TypedUseSelectorHook } from 'react-redux'
139138
import type { RootState, AppDispatch, AppStore } from './store'
140139

141140
// highlight-start
142141
// Use throughout your app instead of plain `useDispatch` and `useSelector`
143-
export const useAppDispatch: () => AppDispatch = useDispatch
144-
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
145-
export const useAppStore: () => AppStore = useStore
142+
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
143+
export const useAppSelector = useSelector.withTypes<RootState>()
144+
export const useAppStore = useStore.withTypes<AppStore>()
146145
// highlight-end
147146
```
148147

@@ -330,14 +329,13 @@ export type AppDispatch = AppStore['dispatch']
330329

331330
// file: lib/hooks.ts noEmit
332331
import { useDispatch, useSelector, useStore } from 'react-redux'
333-
import type { TypedUseSelectorHook } from 'react-redux'
334332
import type { RootState, AppDispatch, AppStore } from './store'
335333

336334
// highlight-start
337335
// Use throughout your app instead of plain `useDispatch` and `useSelector`
338-
export const useAppDispatch: () => AppDispatch = useDispatch
339-
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
340-
export const useAppStore: () => AppStore = useStore
336+
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
337+
export const useAppSelector = useSelector.withTypes<RootState>()
338+
export const useAppStore = useStore.withTypes<AppStore>()
341339
// highlight-end
342340

343341
/* prettier-ignore */

docs/usage/usage-with-typescript.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ The basics of using `configureStore` are shown in [TypeScript Quick Start tutori
3535

3636
### Getting the `State` type
3737

38-
The easiest way of getting the `State` type is to define the root reducer in advance and extract its `ReturnType`.
38+
The easiest way of getting the `State` type is to define the root reducer in advance and extract its `ReturnType`.
3939
It is recommended to give the type a different name like `RootState` to prevent confusion, as the type name `State` is usually overused.
4040

4141
```typescript
@@ -89,7 +89,7 @@ const store = configureStore({
8989

9090
// highlight-start
9191
export type AppDispatch = typeof store.dispatch
92-
export const useAppDispatch: () => AppDispatch = useDispatch // Export a hook that can be reused to resolve types
92+
export const useAppDispatch = useDispatch.withTypes<AppDispatch>() // Export a hook that can be reused to resolve types
9393
// highlight-end
9494

9595
export default store

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"@babel/types": "7.19.3",
5151
"esbuild": "0.19.7",
5252
"jest-snapshot": "29.3.1",
53-
"react-redux": "npm:8.0.2",
53+
"react-redux": "npm:9.1.0",
5454
"react": "npm:18.2.0",
5555
"react-dom": "npm:18.2.0",
5656
"resolve": "1.22.1",

packages/toolkit/src/dynamicMiddleware/react/index.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@ interface ReactDynamicMiddlewareInstance<
5454
Dispatch extends ReduxDispatch<UnknownAction> = ReduxDispatch<UnknownAction>,
5555
> extends DynamicMiddlewareInstance<State, Dispatch> {
5656
createDispatchWithMiddlewareHookFactory: (
57-
context?: Context<
58-
ReactReduxContextValue<State, ActionFromDispatch<Dispatch>>
59-
>,
57+
context?: Context<ReactReduxContextValue<
58+
State,
59+
ActionFromDispatch<Dispatch>
60+
> | null>,
6061
) => CreateDispatchWithMiddlewareHook<State, Dispatch>
6162
createDispatchWithMiddlewareHook: CreateDispatchWithMiddlewareHook<
6263
State,
@@ -71,12 +72,12 @@ export const createDynamicMiddleware = <
7172
const instance = cDM<State, Dispatch>()
7273
const createDispatchWithMiddlewareHookFactory = (
7374
// @ts-ignore
74-
context: Context<
75-
ReactReduxContextValue<State, ActionFromDispatch<Dispatch>>
76-
> = ReactReduxContext,
75+
context: Context<ReactReduxContextValue<
76+
State,
77+
ActionFromDispatch<Dispatch>
78+
> | null> = ReactReduxContext,
7779
) => {
7880
const useDispatch =
79-
// @ts-ignore
8081
context === ReactReduxContext
8182
? useDefaultDispatch
8283
: createDispatchHook(context)

packages/toolkit/src/dynamicMiddleware/tests/react.test-d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const typedInstance = createDynamicMiddleware<number, AppDispatch>()
1515
declare const compatibleMiddleware: Middleware<{}, number, AppDispatch>
1616
declare const incompatibleMiddleware: Middleware<{}, string, AppDispatch>
1717

18-
declare const customContext: Context<ReactReduxContextValue>
18+
declare const customContext: Context<ReactReduxContextValue | null>
1919

2020
declare const addedMiddleware: Middleware<(n: 2) => 2>
2121

packages/toolkit/src/dynamicMiddleware/tests/react.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ describe('createReactDynamicMiddleware', () => {
7171
gDM().prepend(dynamicInstance.middleware).concat(staticMiddleware),
7272
})
7373

74-
const context = React.createContext<ReactReduxContextValue>(null as any)
74+
const context = React.createContext<ReactReduxContextValue | null>(null)
7575

7676
const createDispatchWithMiddlewareHook =
7777
dynamicInstance.createDispatchWithMiddlewareHookFactory(context)

packages/toolkit/src/query/react/ApiProvider.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ import type { Api } from '@reduxjs/toolkit/query'
3232
* conflict with each other - please use the traditional redux setup
3333
* in that case.
3434
*/
35-
export function ApiProvider<A extends Api<any, {}, any, any>>(props: {
35+
export function ApiProvider(props: {
3636
children: any
37-
api: A
37+
api: Api<any, {}, any, any>
3838
setupListeners?: Parameters<typeof setupListeners>[1] | false
39-
context?: Context<ReactReduxContextValue>
39+
context?: Context<ReactReduxContextValue | null>
4040
}) {
4141
const context = props.context || ReactReduxContext
4242
const existingContext = useContext(context)

0 commit comments

Comments
 (0)