Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update React Redux dependency to v9, and update docs to use .withTypes #4308

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions docs/tutorials/typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,12 @@ Since these are actual variables, not types, it's important to define them in a

```ts title="app/hooks.ts"
import { useDispatch, useSelector } from 'react-redux'
import type { TypedUseSelectorHook } from 'react-redux'
import type { RootState, AppDispatch } from './store'

// highlight-start
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
export const useAppSelector = useSelector.withTypes<RootState>()
// highlight-end
```

Expand Down
16 changes: 6 additions & 10 deletions docs/usage/migrating-rtk-2.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,6 @@ React Redux supports creating `hooks` (and `connect`) with a [custom context](ht
import { createContext } from 'react'
import {
ReactReduxContextValue,
TypedUseSelectorHook,
createDispatchHook,
createSelectorHook,
createStoreHook,
Expand All @@ -458,10 +457,9 @@ import { AppStore, RootState, AppDispatch } from './store'
// highlight-next-line
const context = createContext<ReactReduxContextValue>(null as any)

export const useStore: () => AppStore = createStoreHook(context)
export const useDispatch: () => AppDispatch = createDispatchHook(context)
export const useSelector: TypedUseSelectorHook<RootState> =
createSelectorHook(context)
export const useStore = createStoreHook(context).withTypes<AppStore>()
export const useDispatch = createDispatchHook(context).withTypes<AppDispatch>()
export const useSelector = createSelectorHook(context).withTypes<RootState>()
```

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.
Expand All @@ -472,7 +470,6 @@ The above example now becomes:
import { createContext } from 'react'
import {
ReactReduxContextValue,
TypedUseSelectorHook,
createDispatchHook,
createSelectorHook,
createStoreHook,
Expand All @@ -482,10 +479,9 @@ import { AppStore, RootState, AppDispatch } from './store'
// highlight-next-line
const context = createContext<ReactReduxContextValue | null>(null)

export const useStore: () => AppStore = createStoreHook(context)
export const useDispatch: () => AppDispatch = createDispatchHook(context)
export const useSelector: TypedUseSelectorHook<RootState> =
createSelectorHook(context)
export const useStore = createStoreHook(context).withTypes<AppStore>()
export const useDispatch = createDispatchHook(context).withTypes<AppDispatch>()
export const useSelector = createSelectorHook(context).withTypes<RootState>()
```

</div>
Expand Down
6 changes: 3 additions & 3 deletions docs/usage/migrating-to-modern-redux.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1110,13 +1110,13 @@ Per [our standard TypeScript setup and usage guidelines](../tutorials/typescript
First, set up the hooks:

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

// highlight-start
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
export const useAppSelector = useSelector.withTypes<RootState>()
// highlight-end
```

Expand Down
14 changes: 6 additions & 8 deletions docs/usage/nextjs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,13 @@ export type AppDispatch = AppStore['dispatch']

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

// highlight-start
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
export const useAppStore: () => AppStore = useStore
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
export const useAppSelector = useSelector.withTypes<RootState>()
export const useAppStore = useStore.withTypes<AppStore>()
// highlight-end
```

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

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

// highlight-start
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
export const useAppStore: () => AppStore = useStore
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
export const useAppSelector = useSelector.withTypes<RootState>()
export const useAppStore = useStore.withTypes<AppStore>()
// highlight-end

/* prettier-ignore */
Expand Down
4 changes: 2 additions & 2 deletions docs/usage/usage-with-typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The basics of using `configureStore` are shown in [TypeScript Quick Start tutori

### Getting the `State` type

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

```typescript
Expand Down Expand Up @@ -89,7 +89,7 @@ const store = configureStore({

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

export default store
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"@babel/types": "7.19.3",
"esbuild": "0.19.7",
"jest-snapshot": "29.3.1",
"react-redux": "npm:8.0.2",
"react-redux": "npm:9.1.0",
"react": "npm:18.2.0",
"react-dom": "npm:18.2.0",
"resolve": "1.22.1",
Expand Down
7 changes: 6 additions & 1 deletion packages/toolkit/src/dynamicMiddleware/react/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,12 @@ export const createDynamicMiddleware = <
// @ts-ignore
context === ReactReduxContext
? useDefaultDispatch
: createDispatchHook(context)
: createDispatchHook(
context as Context<ReactReduxContextValue<
aryaemami59 marked this conversation as resolved.
Show resolved Hide resolved
State,
ActionFromDispatch<Dispatch>
> | null>,
)
function createDispatchWithMiddlewareHook<
Middlewares extends Middleware<any, State, Dispatch>[],
>(...middlewares: Middlewares) {
Expand Down
5 changes: 4 additions & 1 deletion packages/toolkit/src/dynamicMiddleware/tests/react.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ describe('createReactDynamicMiddleware', () => {
render(<Component />, {
wrapper: ({ children }) => (
<Provider store={store}>
<Provider context={context} store={store2}>
<Provider
context={context as React.Context<ReactReduxContextValue | null>}
store={store2}
>
{children}
</Provider>
</Provider>
Expand Down
3 changes: 2 additions & 1 deletion packages/toolkit/src/query/react/ApiProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ export function ApiProvider<A extends Api<any, {}, any, any>>(props: {
setupListeners?: Parameters<typeof setupListeners>[1] | false
context?: Context<ReactReduxContextValue>
}) {
const context = props.context || ReactReduxContext
const context = (props.context ||
ReactReduxContext) as Context<ReactReduxContextValue | null>
const existingContext = useContext(context)
if (existingContext) {
throw new Error(
Expand Down
2 changes: 1 addition & 1 deletion packages/toolkit/src/query/tests/buildCreateApi.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from 'react-redux'
import { setupApiStore, useRenderCounter } from '../../tests/utils/helpers'

const MyContext = React.createContext<ReactReduxContextValue>(null as any)
const MyContext = React.createContext<ReactReduxContextValue | null>(null)

describe('buildCreateApi', () => {
test('Works with all hooks provided', async () => {
Expand Down
38 changes: 9 additions & 29 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8495,16 +8495,6 @@ __metadata:
languageName: node
linkType: hard

"@types/hoist-non-react-statics@npm:^3.3.1":
version: 3.3.1
resolution: "@types/hoist-non-react-statics@npm:3.3.1"
dependencies:
"@types/react": "npm:*"
hoist-non-react-statics: "npm:^3.3.0"
checksum: 10/071e6d75a0ed9aa0e9ca2cc529a8c15bf7ac3e4a37aac279772ea6036fd0bf969b67fb627b65cfce65adeab31fec1e9e95b4dcdefeab075b580c0c7174206f63
languageName: node
linkType: hard

"@types/html-minifier-terser@npm:^6.0.0":
version: 6.1.0
resolution: "@types/html-minifier-terser@npm:6.1.0"
Expand Down Expand Up @@ -16924,7 +16914,7 @@ __metadata:
languageName: node
linkType: hard

"hoist-non-react-statics@npm:^3.1.0, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2":
"hoist-non-react-statics@npm:^3.1.0, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1":
version: 3.3.2
resolution: "hoist-non-react-statics@npm:3.3.2"
dependencies:
Expand Down Expand Up @@ -24266,35 +24256,25 @@ __metadata:
languageName: node
linkType: hard

"react-redux@npm:8.0.2":
version: 8.0.2
resolution: "react-redux@npm:8.0.2"
"react-redux@npm:9.1.0":
version: 9.1.0
resolution: "react-redux@npm:9.1.0"
dependencies:
"@babel/runtime": "npm:^7.12.1"
"@types/hoist-non-react-statics": "npm:^3.3.1"
"@types/use-sync-external-store": "npm:^0.0.3"
hoist-non-react-statics: "npm:^3.3.2"
react-is: "npm:^18.0.0"
use-sync-external-store: "npm:^1.0.0"
peerDependencies:
"@types/react": ^16.8 || ^17.0 || ^18.0
"@types/react-dom": ^16.8 || ^17.0 || ^18.0
react: ^16.8 || ^17.0 || ^18.0
react-dom: ^16.8 || ^17.0 || ^18.0
react-native: ">=0.59"
redux: ^4
"@types/react": ^18.2.25
react: ^18.0
react-native: ">=0.69"
redux: ^5.0.0
peerDependenciesMeta:
"@types/react":
optional: true
"@types/react-dom":
optional: true
react-dom:
optional: true
react-native:
optional: true
redux:
optional: true
checksum: 10/aea73640041f110d6ee909c24f37128086e324b2857a8e428f76d6737622f2f3004b242191ef6d7e8bc2beb08c4f01698913fe7d2b68634e3fb218c3c97f5074
checksum: 10/e2e5fe1c6965aedf3a80d7d5252ccbe6f231448cc1010ce19036fe8965f996cbafa2f81cacab77e54e75d6a14caa40540b8907459ef36af26b65c14f1bf89d80
languageName: node
linkType: hard

Expand Down