From fabd3e015a220dbfdb7aef0b30a43f9faa5bc9c8 Mon Sep 17 00:00:00 2001 From: lucasgarfield Date: Mon, 4 Dec 2023 16:02:56 +0100 Subject: [PATCH] redux store: define typed useSelector and useDispatch hooks From the RTK docs: ``` Using 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. ---------------------------------------------------------------------- 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: For useSelector, it saves you the need to type (state: RootState) every time 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. ``` source: https://react-redux.js.org/using-react-redux/usage-with-typescript#define-root-state-and-dispatch-types --- src/store/hooks.ts | 7 +++++++ src/store/index.ts | 5 +++++ 2 files changed, 12 insertions(+) create mode 100644 src/store/hooks.ts diff --git a/src/store/hooks.ts b/src/store/hooks.ts new file mode 100644 index 00000000..a1a7827b --- /dev/null +++ b/src/store/hooks.ts @@ -0,0 +1,7 @@ +import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; + +import type { RootState, AppDispatch } from './index'; + +// Use throughout your app instead of plain `useDispatch` and `useSelector` +export const useAppDispatch: () => AppDispatch = useDispatch; +export const useAppSelector: TypedUseSelectorHook = useSelector; diff --git a/src/store/index.ts b/src/store/index.ts index bb43882b..2232ac51 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -31,3 +31,8 @@ export const middleware = (getDefaultMiddleware: Function) => ); export const store = configureStore({ reducer, middleware }); + +// Infer the `RootState` and `AppDispatch` types from the store itself +export type RootState = ReturnType; +// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState} +export type AppDispatch = typeof store.dispatch;