【React】使用 useContext + useReducer 实现一个轻量的状态管理库

使用 useContext + useReducer 实现的轻量级状态管理,适合中小型 React 应用使用。


🧠 实现思路

  1. 使用 createContext 创建两个上下文:StateContextDispatchContext
  2. useReducer 管理状态逻辑。
  3. 创建一个 Provider 组件包裹应用。
  4. 提供两个 hooks:useGlobalState()useGlobalDispatch(),分别获取状态和派发方法。

✅ 示例代码

1️⃣ 创建状态管理库:store.js

jsx 复制代码
import React, { createContext, useReducer, useContext } from 'react';

// 定义初始状态
const initialState = {
  count: 0,
  user: null,
};

// 定义 reducer
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:
      throw new Error(`Unknown action type: ${action.type}`);
  }
}

// 创建两个上下文
const StateContext = createContext(null);
const DispatchContext = createContext(null);

// 创建 Provider
export function GlobalProvider({ children }) {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <StateContext.Provider value={state}>
      <DispatchContext.Provider value={dispatch}>
        {children}
      </DispatchContext.Provider>
    </StateContext.Provider>
  );
}

// 封装 hooks
export function useGlobalState() {
  const context = useContext(StateContext);
  if (context === undefined) {
    throw new Error('useGlobalState must be used within a GlobalProvider');
  }
  return context;
}

export function useGlobalDispatch() {
  const context = useContext(DispatchContext);
  if (context === undefined) {
    throw new Error('useGlobalDispatch must be used within a GlobalProvider');
  }
  return context;
}

2️⃣ 使用示例

App.js
jsx 复制代码
import React from 'react';
import { GlobalProvider } from './store';
import Counter from './Counter';
import User from './User';

function App() {
  return (
    <GlobalProvider>
      <h1>My App</h1>
      <Counter />
      <User />
    </GlobalProvider>
  );
}

export default App;

Counter.js
jsx 复制代码
import React from 'react';
import { useGlobalState, useGlobalDispatch } from './store';

function Counter() {
  const { count } = useGlobalState();
  const dispatch = useGlobalDispatch();

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
    </div>
  );
}

export default Counter;

User.js
jsx 复制代码
import React from 'react';
import { useGlobalState, useGlobalDispatch } from './store';

function User() {
  const { user } = useGlobalState();
  const dispatch = useGlobalDispatch();

  const login = () => {
    dispatch({ type: 'SET_USER', payload: { name: 'Heo Hao' } });
  };

  return (
    <div>
      <h2>User: {user ? user.name : 'Guest'}</h2>
      <button onClick={login}>Login</button>
    </div>
  );
}

export default User;

🧩 优点

  • 不依赖第三方库(如 Redux、Zustand)
  • 轻量、易用、类型安全(可结合 TS)
  • 适合中小项目
相关推荐
777VG5 小时前
PostgreSQL +martin将多张表输出成一个 MVT
前端·数据库·postgresql
mayaairi6 小时前
JS循环语句深度解析:嵌套for、while与do...while
开发语言·前端·javascript
To_OC6 小时前
啃完流式输出:从一个卡顿的 LLM 接口开始,我搞懂了数据流到底怎么 “流”
前端·javascript·llm
阳光是sunny6 小时前
LangGraph实战教程:defer延迟节点——让收尾工作自动排到最后
前端·人工智能·后端
kyriewen7 小时前
我用了三周Claude Code Skills——总结出5条铁律,第3条最反直觉
前端·ai编程·claude
阳光是sunny7 小时前
LangGraph实战教程:控制流详解
前端·人工智能·后端
格尔曼Noah8 小时前
Safari浏览器中如何只允许指定网站下载
前端·safari
用户059540174468 小时前
用了3年Redis,才发现我一直没搞懂缓存一致性测试
前端·css
swipe8 小时前
07|(前端转后全栈)为什么后端也要缓存?从前端缓存思维理解 Redis
前端·后端·全栈
IT小盘9 小时前
05-企业项目统一接入多个大模型-适配器模式实战
前端·人工智能·适配器模式