useReducer
是 React 中用于管理复杂状态逻辑的 Hook,尤其适合处理具有多个子值的状态对象、存在复杂状态转换逻辑或多个操作影响同一状态的场景。它的工作方式类似 Redux 的 reducer 模式,通过 action 驱动状态更新,让状态变化逻辑更可预测、可维护。
type
字段表示操作类型,以及其他必要数据)state
和 action
,返回新的 state
((state, action) => newState
)dispatch(action)
触发 reducer 执行)reducer 是纯函数,根据 action.type
决定如何更新状态,不能直接修改原状态,必须返回新状态。
// 定义 reducer:根据 action 处理状态
function todoReducer(state, action) {
switch (action.type) {
case 'ADD_TODO':
// 返回新数组(不修改原数组)
return [
...state,
{ id: Date.now(), text: action.text, done: false }
];
case 'TOGGLE_TODO':
// 映射新数组,只修改目标项
return state.map(todo =>
todo.id === action.id ? { ...todo, done: !todo.done } : todo
);
case 'DELETE_TODO':
// 过滤掉要删除的项
return state.filter(todo => todo.id !== action.id);
default:
// 未知 action 时返回原状态
return state;
}
}
useReducer
import { useReducer } from 'react';
function TodoApp() {
// 初始化状态(空数组),获取 [状态, dispatch函数]
const [todos, dispatch] = useReducer(todoReducer, []);
const [inputText, setInputText] = useState('');
// 处理添加任务
const handleAdd = () => {
if (!inputText.trim()) return;
// 发送 ADD_TODO 动作,携带必要数据
dispatch({ type: 'ADD_TODO', text: inputText });
setInputText(''); // 清空输入框
};
return (
<div>
<input
value={inputText}
onChange={(e) => setInputText(e.target.value)}
placeholder="输入任务..."
/>
<button onClick={handleAdd}>添加</button>
<ul>
{todos.map(todo => (
<li
key={todo.id}
style={{ textDecoration: todo.done ? 'line-through' : 'none' }}
onClick={() => dispatch({ type: 'TOGGLE_TODO', id: todo.id })}
>
{todo.text}
<button onClick={() => dispatch({ type: 'DELETE_TODO', id: todo.id })}>
删除
</button>
</li>
))}
</ul>
</div>
);
}
当状态逻辑复杂时(例如多字段联动、条件判断多、状态依赖前一个状态),useReducer
比 useState
更清晰:
// 初始状态
const initialState = {
items: [], // 商品列表
total: 0, // 总价
count: 0 // 商品总数
};
// 复杂状态逻辑的 reducer
function cartReducer(state, action) {
switch (action.type) {
case 'ADD_ITEM': {
const existingItem = state.items.find(item => item.id === action.item.id);
let newItems;
if (existingItem) {
// 商品已存在,更新数量
newItems = state.items.map(item =>
item.id === action.item.id
? { ...item, quantity: item.quantity + 1 }
: item
);
} else {
// 新商品,添加到列表
newItems = [...state.items, { ...action.item, quantity: 1 }];
}
// 计算新的总数和总价
const count = newItems.reduce((sum, item) => sum + item.quantity, 0);
const total = newItems.reduce((sum, item) => sum + (item.price * item.quantity), 0);
return { ...state, items: newItems, count, total };
}
case 'REMOVE_ITEM': {
// 实现删除商品逻辑...
}
default:
return state;
}
}
// 组件中使用
function ShoppingCart() {
const [cart, dispatch] = useReducer(cartReducer, initialState);
const addToCart = (product) => {
dispatch({ type: 'ADD_ITEM', item: product });
};
// ...渲染购物车
}
useState
的对比场景 | 推荐使用 | 原因 |
---|---|---|
简单状态(单值) |
| 语法更简洁,无需定义 reducer |
复杂状态(多字段/联动) |
| 状态逻辑集中在 reducer 中,便于调试和复用,避免多个 |
需要预测状态变化 |
| action 可追踪,方便回溯状态变更历史 |
dispatch
会合并处理,类似 setState
。通过 useReducer
,可以将复杂状态逻辑从组件中抽离,让组件更专注于 UI 渲染,同时使状态变化更可预测、易于测试。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。