当前位置: 首页 > news >正文

React15 - 在ruducer中以对象映射替代switch语句

完全可以使用对象映射来代替 Redux reducer 中的 switch case 语句, 这种写法更加简洁、易维护,也符合函数式编程的思想。以下是几种实现方式:

1. 基础对象映射方式

// 定义 action 类型常量
const TYPES = {ADD_TODO: 'ADD_TODO',UPDATE_TODO: 'UPDATE_TODO',DELETE_TODO: 'DELETE_TODO',TOGGLE_TODO: 'TOGGLE_TODO'
};// 创建 action 处理函数的映射对象
const handlers = {[TYPES.ADD_TODO]: (state, action) => ({...state,todos: [...state.todos, action.payload]}),[TYPES.UPDATE_TODO]: (state, action) => ({...state,todos: state.todos.map(todo =>todo.id === action.payload.id ? action.payload : todo)}),[TYPES.DELETE_TODO]: (state, action) => ({...state,todos: state.todos.filter(todo => todo.id !== action.payload)}),[TYPES.TOGGLE_TODO]: (state, action) => ({...state,todos: state.todos.map(todo =>todo.id === action.payload? { ...todo, completed: !todo.completed }: todo)})
};// reducer 使用映射对象
const todoReducer = (state = initialState, action) => {const handler = handlers[action.type];return handler ? handler(state, action) : state;
};

2. 封装成通用函数

// 创建一个通用的 createReducer 函数
const createReducer = (initialState, handlers) => {return (state = initialState, action) => {const handler = handlers[action.type];return handler ? handler(state, action) : state;};
};// 使用示例
const todoReducer = createReducer(initialState, {[TYPES.ADD_TODO]: (state, action) => ({...state,todos: [...state.todos, action.payload]}),[TYPES.UPDATE_TODO]: (state, action) => ({...state,todos: state.todos.map(todo =>todo.id === action.payload.id ? action.payload : todo)})
});

3. 使用 Redux Toolkit(推荐)

Redux Toolkit 内部已经使用了这种模式:

import { createSlice } from '@reduxjs/toolkit';const todosSlice = createSlice({name: 'todos',initialState: {todos: []},reducers: {addTodo: (state, action) => {state.todos.push(action.payload);},updateTodo: (state, action) => {const index = state.todos.findIndex(todo => todo.id === action.payload.id);if (index !== -1) {state.todos[index] = action.payload;}},deleteTodo: (state, action) => {state.todos = state.todos.filter(todo => todo.id !== action.payload);},toggleTodo: (state, action) => {const todo = state.todos.find(todo => todo.id === action.payload);if (todo) {todo.completed = !todo.completed;}}}
});// 自动生成的 action creators
export const { addTodo, updateTodo, deleteTodo, toggleTodo } = todosSlice.actions;
export default todosSlice.reducer;

4. 高级封装 - 支持异步和嵌套

const createReducer = (initialState, handlers) => {// 支持嵌套的 action 类型const flattenHandlers = (obj, prefix = '') => {return Object.keys(obj).reduce((acc, key) => {const fullKey = prefix ? `${prefix}/${key}` : key;if (typeof obj[key] === 'function') {acc[fullKey] = obj[key];} else if (typeof obj[key] === 'object') {Object.assign(acc, flattenHandlers(obj[key], fullKey));}return acc;}, {});};const flatHandlers = flattenHandlers(handlers);return (state = initialState, action) => {// 处理普通 actionif (flatHandlers[action.type]) {return flatHandlers[action.type](state, action);}// 处理异步 action 的三个状态const [baseType, status] = action.type.split('/');if (status && flatHandlers[`${baseType}/${status}`]) {return flatHandlers[`${baseType}/${status}`](state, action);}return state;};
};// 使用示例
const userReducer = createReducer({ data: null, loading: false, error: null },{FETCH_USER: {PENDING: (state) => ({ ...state, loading: true, error: null }),FULFILLED: (state, action) => ({...state,loading: false,data: action.payload}),REJECTED: (state, action) => ({...state,loading: false,error: action.payload})},UPDATE_USER: (state, action) => ({...state,data: { ...state.data, ...action.payload }})}
);

5. TypeScript 版本

type ReducerHandlers<S, A extends Action = AnyAction> = {[key: string]: (state: S, action: A) => S;
};function createReducer<S>(initialState: S,handlers: ReducerHandlers<S>
): (state: S | undefined, action: AnyAction) => S {return (state: S = initialState, action: AnyAction): S => {const handler = handlers[action.type];return handler ? handler(state, action) : state;};
}// 使用示例
interface Todo {id: string;text: string;completed: boolean;
}interface TodoState {todos: Todo[];
}const todoReducer = createReducer<TodoState>({ todos: [] },{[TYPES.ADD_TODO]: (state, action: PayloadAction<Todo>) => ({...state,todos: [...state.todos, action.payload]}),[TYPES.TOGGLE_TODO]: (state, action: PayloadAction<string>) => ({...state,todos: state.todos.map(todo =>todo.id === action.payload? { ...todo, completed: !todo.completed }: todo)})}
);

优点

  1. 更清晰的代码结构:每个 action 类型对应一个处理函数
  2. 易于测试:可以单独测试每个 handler 函数
  3. 易于扩展:添加新的 action 类型只需添加新的键值对
  4. 类型安全:在 TypeScript 中可以获得更好的类型推断
  5. 性能更好:对象属性查找比 switch 语句更快

注意事项

  • 确保处理了未知的 action 类型(返回原状态)
  • 保持 reducer 的纯函数特性
  • 不要直接修改 state(除非使用 Redux Toolkit 的 Immer)

这种模式在实际开发中非常实用,特别是配合 Redux Toolkit,可以让代码更加简洁和可维护。

http://www.jsqmd.com/news/482447/

相关文章:

  • 第10章 矩阵分解:拆解复杂矩阵,简化工程应用
  • Hadoop生态中的数据生命周期管理技术深度剖析
  • **图神经网络实战:用PyTorch Geometric构建社交关系预测模型**在当前人工
  • UV 使用指南
  • **发散创新:基于Python的伦理黑客实战演练——从漏洞探测到防御加固全流程解
  • AI 工程化实战:5分钟带你快速掌握 Function Calling!
  • React15 - 在redux应用中数据存储位置探讨
  • 魔术橡皮 3.1.17 | 无限次AI生图,AI橡皮,图片AI编辑修改
  • 《C++实战项目-高并发内存池》7.大块内存的申请与释放
  • 实战|AI应用架构师用GNN构建智能客服的意图识别
  • Qt Creator + MSVC 2022 64bit 配置 Dump 文件生成与分析流程
  • IBM助力实现费曼量子模拟愿景
  • 微软在Windows 11中新增Xbox模式
  • Redux - 在ruducer中以对象映射替代switch语句
  • 洛谷 B4500:[GESP202603 三级] 凯撒密码 ← 字符串
  • 【原】Python+AI学习笔记(01)大模型调用准备工作 与 OpenAI库基础使用
  • Omsk Metro的题解
  • 东华OJ-进阶题-10-分解质因数(C++)
  • 设计模式2-结构性
  • 一行命令搞定驱动安装!MicroPython 开发有了自己的 “PyPI”包管理平台!
  • Problems(2026/02 ~ 2026/03)
  • React15 - redux中combineReducer的作用
  • 图像拼接对齐
  • Problems(2026/01 ~ 2026/03)
  • 音乐会节目单
  • 「NOI2005」聪聪和可可 的 题解
  • 三角函数 - 重制版
  • Problems(2025 年及更早)
  • 编程对拍助手 autohack-next
  • 如何优化大数据领域的数据建模流程