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

React状态管理Context API + useReducer

在 React 中,Context API + useReducer 是一种轻量级的状态管理方案,适合中小型应用或需要跨组件共享复杂状态的场景。它避免了 Redux 的繁琐配置,同时提供了清晰的状态更新逻辑。


1. 基本使用步骤

(1) 定义 Reducer

类似于 Redux 的 reducer,用于处理状态更新逻辑:

// reducer.js
export const initialState = {count: 0,user: null,
};export function reducer(state, action) {switch (action.type) {case 'INCREMENT':return { ...state, count: state.count + 1 };case 'DECREMENT':return { ...state, count: state.count - 1 };case 'SET_USER':return { ...state, user: action.payload };default:return state;}
}

(2) 创建 Context 和 Provider

使用 createContext 创建 Context,并用 useReducer 管理状态:

// AppContext.js
import { createContext, useReducer } from 'react';
import { initialState, reducer } from './reducer';// 1. 创建 Context
export const AppContext = createContext();// 2. 创建 Provider 组件
export function AppProvider({ children }) {const [state, dispatch] = useReducer(reducer, initialState);return (<AppContext.Provider value={{ state, dispatch }}>{children}</AppContext.Provider>);
}

(3) 在顶层组件包裹 Provider

// App.js
import { AppProvider } from './AppContext';
import Counter from './Counter';function App() {return (<AppProvider><Counter /></AppProvider>);
}

(4) 在子组件使用状态

通过 useContext 获取 statedispatch

// Counter.js
import { useContext } from 'react';
import { AppContext } from './AppContext';export function Counter() {const { state, dispatch } = useContext(AppContext);return (<div><p>Count: {state.count}</p><button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button><button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button></div>);
}

(5) 数据持久化

Context + useReducer 管理的状态是纯内存状态,当页面刷新时,这些数据会丢失,因为 JavaScript 的内存会被清空,恢复到初始状态。
在 React 的 Context + useReducer 架构中实现数据持久化(页面刷新不丢失),可以通过以下方案实现:


手动 localStorage 存储
实现步骤
  1. 初始化时读取 localStorage
  2. 每次更新状态时同步存储
import { createContext, useContext, useReducer, useEffect } from 'react';// 1. 创建 Context
const AppContext = createContext();// 2. 定义 Reducer
function reducer(state, action) {switch (action.type) {case 'INCREMENT':return { ...state, count: state.count + 1 };case 'SET_USER':return { ...state, user: action.payload };default:return state;}
}// 3. 持久化 Provider
function AppProvider({ children }) {const [state, dispatch] = useReducer(reducer,JSON.parse(localStorage.getItem('appState')) || { count: 0, user: null });useEffect(() => {localStorage.setItem('appState', JSON.stringify(state));}, [state]);return (<AppContext.Provider value={{ state, dispatch }}>{children}</AppContext.Provider>);
}
优点
  • 代码简洁,适合小型应用。
  • 无需第三方库。
缺点
  • localStorage 是同步操作,可能阻塞主线程。
  • 存储大小有限(通常 5MB)。
注意事项
  • localStorage 只能存字符串,复杂数据需用 JSON.stringify

2. 进阶优化

(1) 封装自定义 Hook

避免在每个组件里重复写 useContext

// hooks/useAppContext.js
import { useContext } from 'react';
import { AppContext } from '../AppContext';export function useAppContext() {return useContext(AppContext);
}

然后在组件中使用:

const { state, dispatch } = useAppContext();

(2) 优化性能(避免不必要的渲染)

默认情况下,Context 的更新会导致所有消费者组件重新渲染。可以使用 memo + 拆分 Context 优化:

// 拆分多个 Context
const CountContext = createContext();
const UserContext = createContext();// 在 Provider 里分别提供
<CountContext.Provider value={{ countState, countDispatch }}><UserContext.Provider value={{ userState, userDispatch }}>{children}</UserContext.Provider>
</CountContext.Provider>

(3) 结合异步操作

可以在 dispatch 里处理异步逻辑(如 API 请求):

async function fetchUser(dispatch) {try {const user = await fetch('/api/user').then(res => res.json());dispatch({ type: 'SET_USER', payload: user });} catch (error) {dispatch({ type: 'SET_ERROR', payload: error.message });}
}// 在组件中调用
fetchUser(dispatch);

3. 优缺点对比

优点缺点
无需额外库,React 原生支持大型应用可能性能较差(需手动优化)
比 Redux 更轻量异步处理较麻烦(需手动封装)
适合中小型应用调试不如 Redux 方便(无 DevTools)

4. 适用场景

  • 小型/中型应用:不想引入 Redux 或 Zustand 时。
  • 组件层级较深:需要跨多层传递状态时。
  • 简单全局状态:如主题、用户登录信息等。

总结

  • Context + useReducer 是 React 内置的状态管理方案,适合轻量级需求。
  • 对于更复杂的状态管理,可考虑 ZustandRedux Toolkit
  • 如果涉及大量异步逻辑,建议结合 React QuerySWR 使用。

相关文章:

  • C# ExcelWorksheet 贴图
  • React---day9
  • Docker_Desktop开启k8s
  • BIM Revit教程(十一)如何使用机器学习实现 MEP 布局自动化?
  • Palo Alto Networks Expedition存在命令注入漏洞(CVE-2025-0107)
  • Hadolint:Dockerfile 语法检查与最佳实践验证的终极工具
  • Docker Compose 备忘
  • Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
  • DASCTF
  • 通信刚需,AI联手ethernet/ip转profinet网关打通工业技术难关
  • BLEU评分:机器翻译质量评估的黄金标准
  • 实时数据仓库是什么?数据仓库设计怎么做?
  • 选 Agent 还是 Workflow?需求导向的深度解析
  • 不等式中的放缩法
  • AnduinOS使用腾讯会议的坑
  • 电子电路:什么是势垒电容,【势垒电容的定义与原理解析】
  • 层次分析法(Analytic Hierarchy Process, AHP)介绍及使用教程
  • 【HTML】HTML 与 CSS 基础教程
  • 【opencv】基础知识到进阶(更新中)
  • 04-初识css
  • WordPress移动端加搜索框/优化网站打开速度
  • php做的网站怎么入侵/营销推广手段有什么
  • 设计页面宽度/郑州seo代理外包
  • 怎么做网站的轮播图/买转发链接
  • 自己做的网站给人攻击了怎么办/发免费广告电话号码
  • 批发网站怎么做/web网页