欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > React 中hooks之useReducer使用场景和方法总结

React 中hooks之useReducer使用场景和方法总结

2025/3/25 21:52:08 来源:https://blog.csdn.net/qq_34645412/article/details/145212383  浏览:    关键词:React 中hooks之useReducer使用场景和方法总结

1. useReducer 基本概念

useReducer 是 React 的一个 Hook,用于管理复杂的状态逻辑。它接收一个 reducer 函数和初始状态,返回当前状态和 dispatch 函数。

1.1 基本语法

const [state, dispatch] = useReducer(reducer, initialState, init);
  • reducer: (state, action) => newState
  • initialState: 初始状态
  • init: (可选) 惰性初始化函数

2. 基础示例

2.1 简单计数器

function counterReducer(state, action) {switch (action.type) {case 'increment':return { count: state.count + 1 };case 'decrement':return { count: state.count - 1 };default:return state;}
}function Counter() {const [state, dispatch] = useReducer(counterReducer, { count: 0 });return (<div>Count: {state.count}<button onClick={() => dispatch({ type: 'increment' })}>+</button><button onClick={() => dispatch({ type: 'decrement' })}>-</button></div>);
}

3. 复杂状态管理示例

3.1 待办事项列表

const todoReducer = (state, action) => {switch (action.type) {case 'ADD_TODO':return {...state,todos: [...state.todos, {id: Date.now(),text: action.payload,completed: false}]};case 'TOGGLE_TODO':return {...state,todos: state.todos.map(todo =>todo.id === action.payload? { ...todo, completed: !todo.completed }: todo)};case 'DELETE_TODO':return {...state,todos: state.todos.filter(todo => todo.id !== action.payload)};default:return state;}
};function TodoApp() {const [state, dispatch] = useReducer(todoReducer, { todos: [] });const [input, setInput] = useState('');const handleSubmit = (e) => {e.preventDefault();if (!input.trim()) return;dispatch({ type: 'ADD_TODO', payload: input });setInput('');};return (<div><form onSubmit={handleSubmit}><inputvalue={input}onChange={e => setInput(e.target.value)}placeholder="添加待办事项"/><button type="submit">添加</button></form><ul>{state.todos.map(todo => (<li key={todo.id}><spanstyle={{textDecoration: todo.completed ? 'line-through' : 'none'}}onClick={() => dispatch({type: 'TOGGLE_TODO',payload: todo.id})}>{todo.text}</span><button onClick={() => dispatch({type: 'DELETE_TODO',payload: todo.id})}>删除</button></li>))}</ul></div>);
}

3.2 表单状态管理

const formReducer = (state, action) => {switch (action.type) {case 'SET_FIELD':return {...state,[action.field]: action.value};case 'SET_ERROR':return {...state,errors: {...state.errors,[action.field]: action.error}};case 'RESET_FORM':return initialState;default:return state;}
};function ComplexForm() {const initialState = {username: '',email: '',password: '',errors: {}};const [state, dispatch] = useReducer(formReducer, initialState);const handleChange = (e) => {const { name, value } = e.target;dispatch({type: 'SET_FIELD',field: name,value});// 验证逻辑if (name === 'email' && !value.includes('@')) {dispatch({type: 'SET_ERROR',field: 'email',error: '请输入有效的邮箱地址'});}};return (<form><div><inputname="username"value={state.username}onChange={handleChange}placeholder="用户名"/></div><div><inputname="email"value={state.email}onChange={handleChange}placeholder="邮箱"/>{state.errors.email && (<span style={{ color: 'red' }}>{state.errors.email}</span>)}</div><div><inputname="password"type="password"value={state.password}onChange={handleChange}placeholder="密码"/></div><button type="button" onClick={() => dispatch({ type: 'RESET_FORM' })}>重置</button></form>);
}

4. 使用 Immer 简化 Reducer 逻辑

Immer 允许我们以更直观的方式编写 reducer,无需手动处理不可变性。

4.1 安装 Immer

npm install immer

4.2 使用 Immer 重写 Todo 示例

import produce from 'immer';const todoReducer = produce((draft, action) => {switch (action.type) {case 'ADD_TODO':draft.todos.push({id: Date.now(),text: action.payload,completed: false});break;case 'TOGGLE_TODO':const todo = draft.todos.find(t => t.id === action.payload);if (todo) {todo.completed = !todo.completed;}break;case 'DELETE_TODO':const index = draft.todos.findIndex(t => t.id === action.payload);if (index !== -1) {draft.todos.splice(index, 1);}break;}
});

4.3 使用 Immer 简化复杂状态更新

具体参照:[https://immerjs.github.io/immer/zh-CN/example-setstate]

const complexReducer = produce((draft, action) => {switch (action.type) {case 'UPDATE_NESTED_STATE':draft.users[action.userId].preferences.theme = action.theme;break;case 'ADD_ITEM_TO_ARRAY':draft.items[action.categoryId].push(action.item);break;case 'UPDATE_MULTIPLE_FIELDS':Object.assign(draft.form, action.updates);break;}
});function ComplexStateComponent() {const [state, dispatch] = useReducer(complexReducer, {users: {},items: {},form: {}});// 使用示例const updateTheme = (userId, theme) => {dispatch({type: 'UPDATE_NESTED_STATE',userId,theme});};const addItem = (categoryId, item) => {dispatch({type: 'ADD_ITEM_TO_ARRAY',categoryId,item});};
}

5. useReducer 使用场景

  1. 复杂的状态逻辑:当组件状态逻辑复杂,包含多个值时
  2. 相关状态更新:当多个状态更新紧密相关时
  3. 状态依赖其他状态:当状态更新依赖于其他状态值时
  4. 深层状态更新:当需要更新深层嵌套的状态时
  5. 状态更新需要集中管理:当需要在一个地方管理所有状态更新逻辑时

6. 最佳实践

  1. Action 类型常量化
const TODO_ACTIONS = {ADD: 'ADD_TODO',TOGGLE: 'TOGGLE_TODO',DELETE: 'DELETE_TODO'
};
  1. Action Creator 函数化
const createTodo = (text) => ({type: TODO_ACTIONS.ADD,payload: text
});
  1. 使用 TypeScript 定义类型
interface Todo {id: number;text: string;completed: boolean;
}type TodoAction = | { type: 'ADD_TODO'; payload: string }| { type: 'TOGGLE_TODO'; payload: number }| { type: 'DELETE_TODO'; payload: number };const todoReducer = (state: Todo[], action: TodoAction): Todo[] => {// reducer 逻辑
};
  1. 合理拆分 Reducer
const rootReducer = (state, action) => {return {todos: todosReducer(state.todos, action),user: userReducer(state.user, action),ui: uiReducer(state.ui, action)};
};

通过使用 useReducer 和 Immer,我们可以更好地管理复杂的状态逻辑,同时保持代码的可读性和可维护性。Immer 特别适合处理深层嵌套的状态更新,让代码更简洁直观。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词