Skip to content

Commit 7978bbb

Browse files
authored
Merge pull request #3995 from reduxjs/migration-context-typing
2 parents 4afef4a + 1f9deb2 commit 7978bbb

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

docs/usage/migrating-rtk-2.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,58 @@ React-Redux v7 and v8 worked with all versions of React that supported hooks (16
438438

439439
**React-Redux v9 switches to _requiring_ React 18, and does _not_ support React 16 or 17**. This allows us to drop the shim and save a small bit of bundle size.
440440

441+
<div class="typescript-only">
442+
443+
#### Custom context typing
444+
445+
React Redux supports creating `hooks` (and `connect`) with a [custom context](https://react-redux.js.org/api/hooks#custom-context), but typing this has been fairly non-standard. The pre-v9 types required `Context<ReactReduxContextValue>`, but the context default value was usually initialised with `null` (as the hooks use this to make sure they actually have a provided context). This, in "best" cases, would result in something like the below:
446+
447+
```ts title="Pre-v9 custom context"
448+
import { createContext } from 'react'
449+
import {
450+
ReactReduxContextValue,
451+
TypedUseSelectorHook,
452+
createDispatchHook,
453+
createSelectorHook,
454+
createStoreHook,
455+
} from 'react-redux'
456+
import { AppStore, RootState, AppDispatch } from './store'
457+
458+
// highlight-next-line
459+
const context = createContext<ReactReduxContextValue>(null as any)
460+
461+
export const useStore: () => AppStore = createStoreHook(context)
462+
export const useDispatch: () => AppDispatch = createDispatchHook(context)
463+
export const useSelector: TypedUseSelectorHook<RootState> =
464+
createSelectorHook(context)
465+
```
466+
467+
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.
468+
469+
The above example now becomes:
470+
471+
```ts title="v9+ custom context"
472+
import { createContext } from 'react'
473+
import {
474+
ReactReduxContextValue,
475+
TypedUseSelectorHook,
476+
createDispatchHook,
477+
createSelectorHook,
478+
createStoreHook,
479+
} from 'react-redux'
480+
import { AppStore, RootState, AppDispatch } from './store'
481+
482+
// highlight-next-line
483+
const context = createContext<ReactReduxContextValue | null>(null)
484+
485+
export const useStore: () => AppStore = createStoreHook(context)
486+
export const useDispatch: () => AppDispatch = createDispatchHook(context)
487+
export const useSelector: TypedUseSelectorHook<RootState> =
488+
createSelectorHook(context)
489+
```
490+
491+
</div>
492+
441493
### Redux Thunk
442494

443495
#### Thunk Uses Named Exports

0 commit comments

Comments
 (0)