一、4.X版本中核心 API 和用途
1. createStore(reducer, [preloadedState], [enhancer])
用途: 创建 Redux Store
(数据仓库)
参数:
reducer
: 状态更新函数
preloadedState
: 初始状态(可选)
enhancer
: 中间件增强器(如 applyMiddleware)
注意:
现代 Redux 推荐使用 @reduxjs/toolkit 的 configureStore
替代
import { createStore } from 'redux';
// 定义 reducer
const counterReducer = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT': return state + 1;
case 'DECREMENT': return state - 1;
default: return state;
}
};
// 创建 store
const store = createStore(counterReducer);
2. combineReducers(reducers)
用途: 合并多个 reducer
import { combineReducers } from 'redux';
const userReducer = (state = {}, action) => { /* ... */ };
const postReducer = (state = [], action) => { /* ... */ };
const rootReducer = combineReducers({
user: userReducer,
posts: postsReducer
});
3. applyMiddleware(…middlewares)
用途: 应用中间件(如 redux-thunk, redux-saga)
import { applyMiddleware, createStore } from 'redux';
import thunk from 'redux-thunk';
const store = createStore(
rootReducer,
applyMiddleware(thunk, logger)
);
4. compose(…functions)
用途: 组合多个 Store 增强器
const enhancer = compose(applyMiddleware(thunk), devToolsExtension());
二、React-Redux
中常用 Hooks
1. useSelector(selector)
用途: 从 Store
中提取状态
import { useSelector } from 'react-redux';
function Counter() {
// ✅ 正确:直接返回原始值
const count = useSelector(state => state.counter);
// ❌ 错误:每次返回新对象会导致重复渲染
const badSelector = useSelector(state => ({
count: state.counter
}));
return <div>{count}</div>;
}
注意事项:
避免返回新对象导致不必要的渲染(使用浅比较)
复杂选择器建议使用 reselect 库做缓存
2. useDispatch()
用途: 获取 dispatch
函数
import { useDispatch } from 'react-redux';
function Button() {
const dispatch = useDispatch();
// ✅ 正确:在事件处理中调用
const handleClick = () => dispatch({ type: 'INCREMENT' });
// ❌ 错误:避免在渲染中直接调用
// dispatch({ type: 'BAD' });
return <button onClick={handleClick}>+</button>;
}
注意事项:
避免在渲染中直接调用 dispatch
(应在事件回调或 useEffect 中)
3. useStore()
用途: 直接访问 Store 对象(极少使用)
const store = useStore();
三、Redux Toolkit (RTK) 核心 API
1. configureStore(options)
用途: 简化 Store
创建(自动整合中间件和开发工具)
import { configureStore } from '@reduxjs/toolkit';
const store = configureStore({
reducer: {
counter: counterReducer,
},
middleware: (getDefaultMiddleware) => [
...getDefaultMiddleware(),
customMiddleware
],
devTools: process.env.NODE_ENV !== 'production'
});
2. createSlice(options)
用途: 自动生成 action creators 和 reducer
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: (state) => state + 1,
decrement: (state) => state - 1,
// ✅ 使用 Immer 允许"突变"写法
addBy: (state, action) => {
state.value += action.payload;
}
},
// 异步处理 extraReducers
extraReducers: (builder) => {
builder.addCase(fetchUser.fulfilled, (state, action) => {
state.user = action.payload;
})
}
});
// 自动生成 action creators
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
// 自动生成: counterSlice.actions.increment()
// 自动生成: counterSlice.reducer
3. createAsyncThunk(typePrefix, payloadCreator)
用途: 处理异步操作
import { createAsyncThunk } from '@reduxjs/toolkit';
export const fetchUser = createAsyncThunk(
'user/fetch',
async (userId, thunkAPI) => {
try {
const response = await fetch(`/api/users/${userId}`);
return await response.json();
} catch (error) {
return thunkAPI.rejectWithValue(error.message);
}
}
);
// 在组件中使用
dispatch(fetchUser(123));
// 自动生成: fetchUser.pending/fulfilled/rejected 状态
4. createEntityAdapter()
用途: 标准化实体数据管理(如 CRUD
操作)
const usersAdapter = createEntityAdapter();
usersAdapter.addOne(state, user); // 自动处理标准化状态
四、注意事项
1. 不可变性 (Immutability)
必须: Reducer 中禁止直接修改原状态
正确做法:
// 错误: state.value = newValue
// 正确:
return { ...state, value: newValue };
// 或使用 RTK 的 Immer(自动处理不可变):
createSlice({
reducers: {
updateValue: (state, action) => {
state.value = action.payload; // 允许直接修改(Immer 内部处理)
}
}
})
2. 性能优化
避免重复渲染: 使用 useSelector
时选择最小化状态
// 低效写法:每次返回新对象
const badSelect = useSelector(state => ({
items: state.todos.items,
filter: state.todos.filter
}));
// 高效写法:拆分选择器
const items = useSelector(state => state.todos.items);
const filter = useSelector(state => state.todos.filter);
// 或使用 reselect 记忆化
import { createSelector } from 'reselect';
const selectTodos = state => state.todos;
const selectTodoDetails = createSelector(
[selectTodos],
(todos) => ({
items: todos.items,
filter: todos.filter
})
);
批量更新: 合并多个 dispatch
操作(如使用 redux-batched-actions)
3. 异步操作
中间件选择:
简单场景用 redux-thunk
复杂异步流用 redux-saga
或 redux-observable
错误处理: 在 createAsyncThunk
中捕获异常
// 在 extraReducers 中处理错误
const userSlice = createSlice({
name: 'user',
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.status = 'loading';
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.data = action.payload;
state.status = 'succeeded';
})
.addCase(fetchUser.rejected, (state, action) => {
state.error = action.payload;
state.status = 'failed';
});
}
});
4. 项目结构
推荐模式:
按功能模块组织代码(Ducks
模式)
使用 RTK Query
管理 API 请求
分离 UI 状态和业务状态
五、总结建议
优先使用 Redux Toolkit 替代传统 Redux(减少样板代码)
严格遵循不可变性原则:永远不直接修改 state(除非在 RTK 的 createSlice 中)
合理拆分 :reducer
避免单个文件过大
异步操作规范化: 使用 createAsyncThunk
或中间件
性能敏感场景 使用记忆化选择器(reselect
)
通过结合 React Hooks 和 Redux Toolkit
,可以显着简化 Redux
的使用复杂度,同时保持代码的可维护性和性能。