当前位置: 首页 > 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.rkmt.cn/news/1498858.html

相关文章:

  • 网安学习笔记一阶段08——计算机网络基础安全3
  • 【INACCESSIBLE_BOOT_DEVICE】安装 Config Tool 后 Windows 蓝屏,最终通过 VMware 虚拟机解决
  • 徐州懂事星球推荐门店
  • AI 时代,IT 职业教育如何为学习者赋能?——职坐标的 AI+教育实践
  • 什么是 AI 算能基础设施?企业如何选型
  • 2026年执业药师资格考试高频易错题库精编(第005卷)
  • 手把手教你用TI官方库函数重构F28377x CAN代码:告别裸写寄存器
  • Glint:把碎片信息真正变成你的 Obsidian 知识库
  • 从语音合成项目实战出发:手把手教你用 MFA 对齐自己的中文语音数据集
  • 极简日常记录工具:生活备忘、各类提醒全部安排妥当
  • 飞书+龙虾!摄影师局域网外使用龙虾实例!
  • stm32f407读取ov7670(无FIFO)图像灰度值
  • 2026思维导图工具实测:7款主流工具横向对比,按场景选型不踩坑
  • 避开这些坑!DS1302与蓝桥杯单片机I/O冲突的排查与解决实录
  • 机器学习工程师必须掌握的PDF与CDF实战指南
  • NSK VH20AN高防尘直线导轨技术手册
  • 拆开一个烧坏的IGBT模块,手把手教你识别过压、过流、过温的“案发现场”
  • 2026南昌市民常去贵金属回收实体店实测整理 黄金铂金白银回收正规商家前五榜单 - 诚金汇钻回收公司
  • ARM7TDMI-S经典架构解析:LPC2377/78嵌入式系统设计与外设实战
  • 深耕甬城十载 赋能数字转型——宁波森迈商务信息咨询有限公司打造全域小程序综合服务标杆 - 资讯速览
  • PIR、PSI、OT…傻傻分不清?一文讲透隐私计算中几个易混淆的“查询”协议
  • CPS总线安全:GRACYBUS组密钥协议设计与实现
  • 一本书读懂微积分!
  • 不止于点灯:用STM32H7的复杂时钟树驱动高精度外设(CubeMx配置SPI/I2S实战)
  • 从‘玻璃丝’到‘信息高速公路’:用大白话图解光纤通信的核心原理(附公式推导避坑指南)
  • LPC2468低功耗与电气特性实战:从数据手册到稳定设计
  • 2026濮阳贵金属旧料回收优质门店排行 TOP5 黄金白银铂金金条回收正规老店实地走访整理 - 信誉隆金银铂奢回收
  • 从食堂打饭到银行排队:用C++优先队列(priority_queue)模拟‘接水问题’的通用思路
  • 手把手教你点亮480x480圆形屏:ST7701s双通道MIPI驱动代码逐行解析
  • 用ESP8266和巴法云,10分钟搞定Alexa智能灯泡(附继电器接线图)