From harness-claude
Configures Redux store using configureStore with typed hooks, middleware, and Provider wiring in React apps. For initializing new apps, migrating from createStore, or adding custom middleware.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Configure the Redux store with configureStore, typed hooks, middleware, and Provider wiring
Types Redux Toolkit state, actions, thunks, hooks, and middleware with full TypeScript inference and minimal annotations. Use for setup, fixing type errors in slices, extraReducers, or components.
Guides Redux and Redux Toolkit for global state management: slices, stores, actions, reducers, hooks, selectors, middleware, async thunks.
Creates Zustand stores with TypeScript types, subscribeWithSelector middleware, separated state/actions, individual selectors, and non-React subscriptions. For React state management.
Share bugs, ideas, or general feedback.
Configure the Redux store with configureStore, typed hooks, middleware, and Provider wiring
createStore to Redux Toolkit's configureStoreuseDispatch and useSelector hooksstore/index.ts as the single store configuration file. Export the store, RootState, AppDispatch, and typed hooks from here.configureStore — it automatically sets up Redux DevTools, thunk middleware, and the serializable check middleware.reducer field. Do not use combineReducers separately unless you need reducer injection.RootState and AppDispatch types from the store itself, not manually. This keeps types in sync as slices are added.useAppDispatch, useAppSelector) once and import them everywhere instead of plain useDispatch/useSelector.<Provider store={store}>.middleware callback — never replace the defaults unless you have a specific reason.// store/index.ts
import { configureStore } from '@reduxjs/toolkit';
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import todosReducer from '../features/todos/todos.slice';
import usersReducer from '../features/users/users.slice';
export const store = configureStore({
reducer: {
todos: todosReducer,
users: usersReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
// Ignore specific action paths if needed (e.g., for dates or file objects)
ignoredActions: ['persist/PERSIST'],
},
}),
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
// Typed hooks — use these throughout the app
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
// app entry point
import { Provider } from 'react-redux';
import { store } from './store';
function App() {
return (
<Provider store={store}>
<Root />
</Provider>
);
}
What configureStore does automatically: Combines reducers, adds redux-thunk, enables Redux DevTools Extension, adds development-only middleware (serializable check, immutability check).
Custom middleware: The middleware callback receives getDefaultMiddleware which returns a Tuple. Chain custom middleware with .concat() — do not spread into an array.
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(logger, apiMiddleware),
Lazy-loaded reducer injection: For code-split apps, use store.replaceReducer() or RTK's combineSlices (RTK 2.0+) for dynamic slice injection without upfront registration.
Common mistakes:
store directly in components (use hooks + Provider instead)RootState manually instead of inferring from store.getStatehttps://redux-toolkit.js.org/api/configureStore