使用 Redux Toolkit(@reduxjs/toolkit
v2.6.1)封装一个模块化的 store
,并实现工程化的 Redux 管理,需要考虑模块化、可扩展性和清晰的文件结构。以下是一个完整的实现方案,适用于模块化管理的 Redux 项目。
项目结构
假设你的项目结构如下:
python
src/
├── store/
│ ├── index.ts # store 配置入口
│ ├── rootReducer.ts # 根 reducer 组合
│ ├── hooks.ts # 自定义 hooks
│ └── modules/ # 模块化切片目录
│ ├── counter/ # 示例模块:counter
│ │ ├── slice.ts # counter 的 slice
│ │ └── types.ts # counter 的类型定义
│ └── user/ # 示例模块:user
│ ├── slice.ts # user 的 slice
│ └── types.ts # user 的类型定义
├── App.tsx # 应用入口
└── ...
实现步骤
1. 安装依赖
确保已安装 Redux Toolkit 和 React-Redux:
bash
npm install @reduxjs/[email protected] react-redux
2. 创建模块化切片(以 counter 和 user 为例)
counter 模块:src/store/modules/counter/slice.ts
typescript
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
// 状态类型
export interface CounterState {
value: number;
}
const initialState: CounterState = {
value: 0,
};
/**
* Counter 模块的 Redux slice
*/
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload;
},
},
});
// 导出 actions 和 reducer
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
user 模块:src/store/modules/user/slice.ts
typescript
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
// 状态类型
export interface UserState {
name: string;
isLoggedIn: boolean;
}
const initialState: UserState = {
name: '',
isLoggedIn: false,
};
/**
* User 模块的 Redux slice
*/
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
login: (state, action: PayloadAction<string>) => {
state.name = action.payload;
state.isLoggedIn = true;
},
logout: (state) => {
state.name = '';
state.isLoggedIn = false;
},
},
});
// 导出 actions 和 reducer
export const { login, logout } = userSlice.actions;
export default userSlice.reducer;
3. 组合根 Reducer(src/store/rootReducer.ts
)
将所有模块的 reducer 组合成一个根 reducer:
typescript
import { combineReducers } from '@reduxjs/toolkit';
import counterReducer from './modules/counter/slice';
import userReducer from './modules/user/slice';
const rootReducer = combineReducers({
counter: counterReducer,
user: userReducer,
});
export type RootState = ReturnType<typeof rootReducer>;
export default rootReducer;
RootState
类型用于后续类型推导,确保类型安全。
4. 配置 Store(src/store/index.ts
)
使用 configureStore
创建一个模块化的 store:
typescript
import { configureStore } from '@reduxjs/toolkit';
import rootReducer from './rootReducer';
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false, // 可选:关闭序列化检查(如果需要非序列化状态)
}),
devTools: process.env.NODE_ENV !== 'production', // 开发环境启用 Redux DevTools
});
export default store;
// 导出类型用于 hooks
export type AppDispatch = typeof store.dispatch;
configureStore
自带默认中间件(如redux-thunk
),并支持 Redux DevTools。AppDispatch
类型用于类型安全的dispatch
。
5. 创建自定义 Hooks(src/store/hooks.ts
)
为了方便在 React 组件中使用类型安全的 Redux,创建自定义 hooks:
typescript
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import { RootState, AppDispatch } from '../store';
// 类型安全的 useSelector
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
// 类型安全的 useDispatch
export const useAppDispatch = () => useDispatch<AppDispatch>();
6. 在应用中集成(src/App.tsx
)
将 store 提供给 React 应用,并使用模块化的 Redux:
typescript
import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import Counter from './Counter';
import User from './User';
const App: React.FC = () => {
return (
<Provider store={store}>
<div>
<h1>Redux Toolkit Modular Demo</h1>
<Counter />
<User />
</div>
</Provider>
);
};
export default App;
示例组件:src/Counter.tsx
typescript
import React from 'react';
import { useAppSelector, useAppDispatch } from './store/hooks';
import { increment, decrement, incrementByAmount } from './store/modules/counter/slice';
const Counter: React.FC = () => {
const count = useAppSelector((state) => state.counter.value);
const dispatch = useAppDispatch();
return (
<div>
<h2>Counter: {count}</h2>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
<button onClick={() => dispatch(incrementByAmount(5))}>Add 5</button>
</div>
);
};
export default Counter;
示例组件:src/User.tsx
typescript
import React from 'react';
import { useAppSelector, useAppDispatch } from './store/hooks';
import { login, logout } from './store/modules/user/slice';
const User: React.FC = () => {
const { name, isLoggedIn } = useAppSelector((state) => state.user);
const dispatch = useAppDispatch();
return (
<div>
<h2>User: {isLoggedIn ? name : 'Not logged in'}</h2>
<button onClick={() => dispatch(login('Alice'))}>Login as Alice</button>
<button onClick={() => dispatch(logout())}>Logout</button>
</div>
);
};
export default User;
特点与优势
-
模块化管理:
- 每个功能模块(如
counter
、user
)都有独立的slice
文件,包含状态、reducer 和 actions。 - 通过
rootReducer
组合所有模块,保持清晰的层次结构。
- 每个功能模块(如
-
类型安全:
- 使用 TypeScript 定义状态和 dispatch 类型,避免类型错误。
- 自定义
useAppSelector
和useAppDispatch
提供类型支持。
-
Redux Toolkit v2.6.1 特性:
- 使用
createSlice
简化 reducer 和 action 创建。 configureStore
自带默认中间件和 DevTools 支持。- 支持异步逻辑(可通过
createAsyncThunk
扩展)。
- 使用
-
可扩展性:
- 添加新模块时,只需创建新的
slice
并在rootReducer
中注册即可。
- 添加新模块时,只需创建新的
扩展建议
-
异步逻辑 :使用
createAsyncThunk
处理 API 请求。typescriptimport { createAsyncThunk } from '@reduxjs/toolkit'; export const fetchUser = createAsyncThunk('user/fetch', async (id: string) => { const response = await fetch(`/api/user/${id}`); return response.json(); });
-
中间件:根据需要添加自定义中间件(如日志中间件)。
-
RTK Query:如果需要数据获取和缓存,可以集成 Redux Toolkit Query。
这个封装方案已经完全模块化,适用于中小型到大型项目。你可以根据具体需求调整目录结构或添加更多功能。如果有其他问题或需要优化某个部分,请告诉我!