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

03-状态管理与路由——01-Context + useReducer 模式

Context + useReducer 模式

一、为什么需要状态管理?

1.1 Props Drilling 问题

// ❌ 层层传递,繁琐且难以维护 <GrandParent user={user}> <Parent user={user}> <Child user={user}> <GrandChild user={user} /> </Child> </Parent> </GrandParent>

1.2 解决方案对比

方案适用场景优点缺点
Props简单父子组件简单直接层级深时繁琐
Context跨层级传递避免 props drilling过度使用影响性能
Context + useReducer中等复杂度应用轻量、内置比 Zustand 代码多
Zustand/Redux大型应用功能强大学习成本

二、Context + useReducer 基础

2.1 创建状态管理

// store/AppContext.js import React, { createContext, useContext, useReducer } from 'react'; // 1. 定义初始状态 const initialState = { user: null, theme: 'light', count: 0, notifications: [] }; // 2. 定义 Action 类型 const ACTIONS = { SET_USER: 'SET_USER', TOGGLE_THEME: 'TOGGLE_THEME', INCREMENT: 'INCREMENT', DECREMENT: 'DECREMENT', ADD_NOTIFICATION: 'ADD_NOTIFICATION', REMOVE_NOTIFICATION: 'REMOVE_NOTIFICATION' }; // 3. 定义 Reducer function appReducer(state, action) { switch (action.type) { case ACTIONS.SET_USER: return { ...state, user: action.payload }; case ACTIONS.TOGGLE_THEME: return { ...state, theme: state.theme === 'light' ? 'dark' : 'light' }; case ACTIONS.INCREMENT: return { ...state, count: state.count + 1 }; case ACTIONS.DECREMENT: return { ...state, count: state.count - 1 }; case ACTIONS.ADD_NOTIFICATION: return { ...state, notifications: [...state.notifications, action.payload] }; case ACTIONS.REMOVE_NOTIFICATION: return { ...state, notifications: state.notifications.filter(n => n.id !== action.payload) }; default: return state; } } // 4. 创建 Context const AppContext = createContext(); // 5. Provider 组件 export function AppProvider({ children }) { const [state, dispatch] = useReducer(appReducer, initialState); return <AppContext.Provider value={{ state, dispatch }}>{children}</AppContext.Provider>; } // 6. 自定义 Hook export function useAppContext() { const context = useContext(AppContext); if (!context) throw new Error('useAppContext must be used within AppProvider'); return context; }

2.2 使用状态管理

function Counter() { const { state, dispatch } = useAppContext(); return ( <div> <p>计数: {state.count}</p> <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button> <button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button> </div> ); } function ThemeToggle() { const { state, dispatch } = useAppContext(); return ( <button onClick={() => dispatch({ type: 'TOGGLE_THEME' })}> 当前主题: {state.theme} </button> ); }

三、实战:Todo 应用

3.1 Store 定义

const initialState = { todos: [], filter: 'all', loading: false, error: null }; const ACTIONS = { ADD_TODO: 'ADD_TODO', TOGGLE_TODO: 'TOGGLE_TODO', DELETE_TODO: 'DELETE_TODO', SET_FILTER: 'SET_FILTER', SET_LOADING: 'SET_LOADING' }; function todoReducer(state, action) { switch (action.type) { case ACTIONS.ADD_TODO: return { ...state, todos: [...state.todos, action.payload] }; case ACTIONS.TOGGLE_TODO: return { ...state, todos: state.todos.map(todo => todo.id === action.payload ? { ...todo, completed: !todo.completed } : todo ) }; case ACTIONS.DELETE_TODO: return { ...state, todos: state.todos.filter(todo => todo.id !== action.payload) }; case ACTIONS.SET_FILTER: return { ...state, filter: action.payload }; default: return state; } }

四、性能优化

4.1 拆分 Context

// 按职责拆分,避免不必要的重渲染 const UserContext = createContext(); const ThemeContext = createContext(); const NotificationContext = createContext();

4.2 使用 useMemo 优化值

function AppProvider({ children }) { const [state, dispatch] = useReducer(reducer, initialState); const value = useMemo(() => ({ state, dispatch }), [state]); return <AppContext.Provider value={value}>{children}</AppContext.Provider>; }

五、小结

要点说明
适用场景中小型应用、跨层级状态
核心组合Context + useReducer
性能优化拆分 Context、useMemo

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

相关文章:

  • 【设计模式-策略模式】
  • 徐州懂事星球推荐门店
  • AI 时代,IT 职业教育如何为学习者赋能?——职坐标的 AI+教育实践
  • 倒置显微镜生产厂家推荐|蔡司、徕卡、尼康与实了个验集团对比分析 - 实了个验
  • 2026山西地区配电箱厂家综合实力排行及选型参考指南 - 起跑123
  • 【INACCESSIBLE_BOOT_DEVICE】安装 Config Tool 后 Windows 蓝屏,最终通过 VMware 虚拟机解决
  • 【计算机毕业设计案例】基于springboot+微信小程序的文化旅游小程序系统(程序+文档+讲解+定制)
  • 影刀RPA完全指南_非技术人员学习自动化的心智模型
  • 网安学习笔记一阶段08——计算机网络基础安全3
  • AI产品经理 vs AI研发工程师:大厂为什么开始招中学生了?
  • 2026武汉防水补漏哪家靠谱?正规公司排名及避坑价格指南 - 苏易修缮
  • 什么是 AI 算能基础设施?企业如何选型
  • 影刀RPA实操指南_1688商品数据自动化采集
  • 深入解析LPC55S3x:从Flexcomm到EdgeLock,如何高效利用外设与安全子系统
  • Windows 10/11 下用 Conda 搞定 MFA 2.0 语音对齐,保姆级避坑指南(含网络问题解决)
  • VScode cmake mingw 使用opencv调用笔记本摄像头进行人脸识别,并生成动态库、静态库
  • 2026年执业药师资格考试高频易错题库精编(第005卷)
  • 2026全球AI大模型大战:OpenAI冲击IPO,Meta豪赌超级智能,AI Agent时代来了
  • 从 PMF 到规模化:AI Agent Harness Engineering 创业全生命周期路线图
  • 两款全网难找的“神器”,用过的都说牛!
  • 数字孪生与 Agent Harness 的协同仿真
  • 【知识图谱】语义本体的演进之路:从严谨到敏捷的范式转变
  • Glint:把碎片信息真正变成你的 Obsidian 知识库
  • 2026 成都爱彼回收避坑攻略,皇家橡树系列交易防骗要点 - 奢侈品回收评测
  • 华为eNSP实验避坑指南:配置OSPF多区域时,90%新手都会忽略的‘骨干区域’连通性检查
  • 从语音合成项目实战出发:手把手教你用 MFA 对齐自己的中文语音数据集
  • 手把手教你用TI官方库函数重构F28377x CAN代码:告别裸写寄存器
  • 极简日常记录工具:生活备忘、各类提醒全部安排妥当
  • Python 异步编程从入门到实战:告别阻塞,让你的代码效率起飞
  • 鸿蒙新特性:Menu 下拉菜单深度解析 —— 工具栏与操作面板