useReducer 集中式管理组件的状态
1️⃣ 基本概念
useReducer 是 React 提供的 管理组件状态的一种 Hook ,功能上类似于 useState,但是它更适合状态逻辑复杂或依赖前一个状态的情况。
它的核心思想:
- 状态(state) 是不可变的。
- 状态更新逻辑 写在一个函数里(Reducer)。
- 通过 dispatch(action) 来触发状态更新,而不是直接 setState。
1.1 函数签名
scss
const [state, dispatch] = useReducer(reducer, initialState, init?)
参数解释:
| 参数 | 说明 |
|---|---|
reducer |
一个函数 (state, action) => newState,决定状态如何更新 |
initialState |
初始状态 |
init |
可选函数,用于惰性初始化状态(通常不需要) |
返回值:
state:当前状态(只读)dispatch:派发 action 的函数,用来触发状态更新
1.2 Reducer 函数
Reducer 是状态更新逻辑的核心:
php
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: 0 };
default:
return state;
}
}
特点:
- 不直接修改 state,而是返回一个新的状态对象。
- 通常使用
switch(action.type)来判断不同动作。 action可以是对象,也可以是任意自定义格式(推荐对象,包含type字段)。
1.3 最简单的例子
javascript
import React, { useReducer } from 'react';
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: 0 };
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
}
export default Counter;
✅ 可以看到:
- 所有状态更新逻辑都集中在 reducer 里。
- 组件内部不需要关心更新细节,只需要
dispatch对应的 action。
2️⃣ useReducer vs useState
| 方面 | useState | useReducer |
|---|---|---|
| 适用场景 | 简单状态(计数器、输入框) | 复杂状态逻辑、多个子值依赖前一个状态 |
| 状态更新 | setState(newValue) | dispatch(action) |
| 状态逻辑 | 分散在多个 setState | 集中在 reducer 函数 |
| 可读性 | 简单 | 状态逻辑清晰、易于维护 |
| 性能优化 | 不如 useReducer | dispatch 不会改变引用,可避免重复渲染 |
总结:
- 简单场景用
useState就够了。 - 状态更新复杂(多分支、多子值依赖)用
useReducer更清晰。
3️⃣ 更复杂的例子:表单管理
假设有一个复杂表单:
javascript
import React, { useReducer } from 'react';
const initialState = {
username: '',
email: '',
password: '',
};
function reducer(state, action) {
switch (action.type) {
case 'updateField':
return { ...state, [action.field]: action.value };
case 'reset':
return initialState;
default:
return state;
}
}
function Form() {
const [state, dispatch] = useReducer(reducer, initialState);
const handleChange = (e) => {
dispatch({ type: 'updateField', field: e.target.name, value: e.target.value });
};
const handleReset = () => {
dispatch({ type: 'reset' });
};
return (
<form>
<input name="username" value={state.username} onChange={handleChange} placeholder="Username" />
<input name="email" value={state.email} onChange={handleChange} placeholder="Email" />
<input name="password" type="password" value={state.password} onChange={handleChange} placeholder="Password" />
<button type="button" onClick={handleReset}>Reset</button>
</form>
);
}
export default Form;
✅ 优点:
- 所有字段更新逻辑集中在 reducer 中。
- 方便扩展,比如添加表单校验、提交状态等。
4️⃣ useReducer 的惰性初始化
有时候初始化 state 很复杂,可以用第三个参数 init:
kotlin
function init(initialCount) {
return { count: initialCount };
}
const [state, dispatch] = useReducer(reducer, 0, init);
好处:
- 性能优化 :只有第一次 render 会调用
init。 - 避免每次 render 都执行复杂计算。
5️⃣ 总结
-
useReducer 是 useState 的增强版,适合复杂状态逻辑。
-
核心概念:
- Reducer:决定状态如何变化
- State:组件状态(只读)
- Dispatch:触发状态更新
-
优点:
- 状态更新逻辑集中,易维护
- 方便管理复杂或嵌套状态
- 和 Redux 思想一致,易迁移
-
使用场景:
-
多个状态值相互依赖
-
多分支的状态更新逻辑
-
想用
dispatch(action)统一管理
-
总结
useReducer 管理的 state 本身只会在 dispatch 被调用时改变。每次组件重新渲染时,整个组件函数会重新执行,但 state 不会自动变化,仍然保持最新的值