Redux 状态管理:Store、Action 与 Reducer
什么是 Redux?
Redux 是一个用于 JavaScript 应用的可预测状态容器。它帮助你编写行为一致、可测试的应用,并且可以运行在不同环境(客户端、服务器、原生应用)中。核心思想是整个应用的状态被存储在一个单一的 Store 中,状态只能通过派发(dispatch)Action 来改变,而变化的逻辑由纯函数 Reducer 来定义。
相比组件间层层传递 props 或使用 Context,Redux 提供了一种集中式、可控的状态管理方式,特别适合中大型应用中的复杂状态逻辑。
Redux 核心三要素
Redux 的设计围绕以下三个不可分割的概念,理解它们就能掌握 Redux 的精髓。
Store —— 唯一的数据源
Store 是一个保存整个应用状态树的容器。在整个应用中只有一个 Store。
- 通过
createStore方法创建(在 Redux Toolkit 中通常使用configureStore)。 - 提供
getState()获取当前状态。 - 提供
dispatch(action)更新状态。 - 允许通过
subscribe(listener)注册监听器,状态变化时自动触发。
import { createStore } from 'redux';
import rootReducer from './reducers';
const store = createStore(rootReducer);
现代 Redux 推荐使用
@reduxjs/toolkit中的configureStore,它封装了更好的默认配置(如 Redux DevTools 和中间件)。
Action —— 描述“发生了什么”
Action 是一个普通的 JavaScript 对象,它是改变状态的唯一途径。Store 只能通过派发 Action 来触发状态更新。
Action 对象必须包含一个 type 字段,用于描述动作的类型(通常是字符串常量)。除此之外,可以携带任意数据作为 payload。
// Action 示例
const addTodoAction = {
type: 'todos/todoAdded',
payload: '学习 Redux'
};
// 通常使用 Action Creator 函数来生成 Action
const addTodo = (text) => ({
type: 'todos/todoAdded',
payload: text
});
规则:永远不要直接修改状态,而是通过派发 Action 让 Reducer 返回新状态。这样可以保证数据流清晰可溯,方便调试和时间旅行。
Reducer —— 描述状态如何改变
Reducer 是一个纯函数,接收当前状态和 Action 作为参数,返回新的状态。它具体描述了 Action 如何将状态从旧值转变为新值。
(state, action) => newState
必须遵守的原则:
- 不要直接修改传入的 state 参数(即不可变更新)。
- 不能执行副作用(如 API 调用、路由跳转)。
- 对于未知的 action type,必须返回原 state。
const initialState = { value: 0 };
function counterReducer(state = initialState, action) {
switch (action.type) {
case 'counter/incremented':
return { ...state, value: state.value + 1 }; // 不可变更新
case 'counter/decremented':
return { ...state, value: state.value - 1 };
default:
return state;
}
}
多个 Reducer 可以通过 combineReducers 组合起来,分别管理状态树的不同部分。
三者如何协作
Redux 的数据流是严格的单向流动:
- Store 保存初始状态,并交给
dispatch一个 Action。 - UI 中触发某个事件(如按钮点击),调用
store.dispatch(action)。 - Store 将当前的 state 和收到的 action 传递给 Reducer。
- Reducer 是一个纯函数,它计算并返回全新的 state,Store 会保存这个新状态。
- Store 通知所有订阅了它的 UI 组件,状态已更新,组件根据新数据重新渲染。
这个循环保证了状态的可预测性和可维护性,每一次状态变化都有迹可循。
使用 Redux Toolkit 简化代码
在现代 Redux 开发中,强烈推荐使用 Redux Toolkit (RTK)。它是官方推荐的工具集,解决了传统 Redux 上手难、样板代码多的问题。
创建 Slice(合并 Action 和 Reducer)
使用 createSlice 可以一次性定义状态、reducer 逻辑和相应的 action creator。
import { createSlice } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
incremented: (state) => {
// Redux Toolkit 内部使用了 Immer,允许直接“修改”state
state.value += 1;
},
decremented: (state) => {
state.value -= 1;
},
incrementedByAmount: (state, action) => {
state.value += action.payload;
}
}
});
export const { incremented, decremented, incrementedByAmount } = counterSlice.actions;
export default counterSlice.reducer;
配置 Store
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
const store = configureStore({
reducer: {
counter: counterReducer
}
});
在 React 组件中使用
通过 react-redux 的 hooks 连接组件和 Store:
import { useSelector, useDispatch } from 'react-redux';
import { incremented, decremented } from './counterSlice';
function Counter() {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<button onClick={() => dispatch(decremented())}>-</button>
<span>{count}</span>
<button onClick={() => dispatch(incremented())}>+</button>
</div>
);
}
小结
- Store:统一保管所有状态,通过
dispatch触发变更。 - Action:描述“要做什么”的对象,带有
type和可选的payload。 - Reducer:纯函数,定义状态如何响应 Action 并返回新状态。
- Redux Toolkit:官方推荐工具,大幅简化 Redux 代码,使状态管理更直观高效。
掌握这三个核心概念,你就具备了使用 Redux 管理复杂应用状态的基础能力。下一步可以深入学习异步逻辑(如 createAsyncThunk)、实体适配器(createEntityAdapter)等高级特性。