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

createContext+useContext+useReducer组合管理React复杂状态

createContextuseContextuseReducer 的组合是 React 中管理全局状态的一种常见模式。这种模式非常适合在不引入第三方状态管理库(如 Redux)的情况下,管理复杂的全局状态。

以下是一个经典的例子,展示如何使用 createContextuseContextuseReducer 来实现一个简单的全局状态管理。

示例:Todo 应用

我们将实现一个简单的 Todo 应用,支持以下功能:

  1. 添加任务
  2. 删除任务
  3. 切换任务完成状态

1. 定义全局状态和操作

TodoContext.tsx

import React, { createContext, useReducer, useContext, ReactNode } from 'react';

// 定义 Todo 项的类型
interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

// 定义全局状态的类型
interface TodoState {
  todos: Todo[];
}

// 定义操作类型
type TodoAction =
  | { type: 'ADD_TODO'; payload: string }
  | { type: 'TOGGLE_TODO'; payload: number }
  | { type: 'DELETE_TODO'; payload: number };

// 定义初始状态
const initialState: TodoState = {
  todos: [],
};

// 定义 reducer 函数
const todoReducer = (state: TodoState, action: TodoAction): TodoState => {
  switch (action.type) {
    case 'ADD_TODO':
      return {
        ...state,
        todos: [
          ...state.todos,
          { id: Date.now(), text: action.payload, completed: false },
        ],
      };
    case 'TOGGLE_TODO':
      return {
        ...state,
        todos: state.todos.map((todo) =>
          todo.id === action.payload
            ? { ...todo, completed: !todo.completed }
            : todo
        ),
      };
    case 'DELETE_TODO':
      return {
        ...state,
        todos: state.todos.filter((todo) => todo.id !== action.payload),
      };
    default:
      return state;
  }
};

// 创建 Context
const TodoContext = createContext<{
  state: TodoState;
  dispatch: React.Dispatch<TodoAction>;
} | null>(null);

// 创建 Provider 组件
export const TodoProvider = ({ children }: { children: ReactNode }) => {
  const [state, dispatch] = useReducer(todoReducer, initialState);

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

// 自定义 Hook,用于使用 TodoContext
export const useTodoContext = () => {
  const context = useContext(TodoContext);
  if (!context) {
    throw new Error('useTodoContext must be used within a TodoProvider');
  }
  return context;
};

2. 使用全局状态

App.tsx

import React, { useState } from 'react';
import { TodoProvider, useTodoContext } from './TodoContext';

const TodoList = () => {
  const { state, dispatch } = useTodoContext();

  return (
    <div>
      <h2>Todo List</h2>
      <ul>
        {state.todos.map((todo) => (
          <li key={todo.id}>
            <span
              style={{
                textDecoration: todo.completed ? 'line-through' : 'none',
                cursor: 'pointer',
              }}
              onClick={() => dispatch({ type: 'TOGGLE_TODO', payload: todo.id })}
            >
              {todo.text}
            </span>
            <button onClick={() => dispatch({ type: 'DELETE_TODO', payload: todo.id })}>
              Delete
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
};

const AddTodo = () => {
  const { dispatch } = useTodoContext();
  const [text, setText] = useState('');

  const handleAddTodo = () => {
    if (text.trim()) {
      dispatch({ type: 'ADD_TODO', payload: text });
      setText('');
    }
  };

  return (
    <div>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Add a new task"
      />
      <button onClick={handleAddTodo}>Add</button>
    </div>
  );
};

const App = () => {
  return (
    <TodoProvider>
      <h1>Todo App</h1>
      <AddTodo />
      <TodoList />
    </TodoProvider>
  );
};

export default App;

3. 代码解释

  1. TodoContext:
    • 使用 createContext 创建一个全局状态的上下文。
    • 使用 useReducer 管理全局状态和操作。
  2. TodoProvider:
    • 包裹应用的根组件,提供全局状态和 dispatch 方法。
  3. useTodoContext:
    • 自定义 Hook,用于简化 useContext 的使用,并确保上下文只能在 TodoProvider 内部使用。
  4. todoReducer:
    • 定义了如何根据不同的操作(ADD_TODO、TOGGLE_TODO、DELETE_TODO)更新全局状态。
  5. 组件分离:
    • AddTodo 组件负责添加任务。
    • TodoList 组件负责显示任务列表,并支持切换任务状态和删除任务。

4. 优势

  • 清晰的状态管理
    • 使用 useReducer 将状态更新逻辑集中在一个地方,便于维护和扩展。
  • 全局状态共享
    • 使用 createContext 和 useContext 实现全局状态共享,无需手动传递 props。
  • 组件解耦
    • 通过上下文和 dispatch,各组件可以独立处理自己的逻辑,而无需直接依赖其他组件。

5. 总结

createContext + useContext + useReducer 是一种轻量级的全局状态管理方案,适合中小型项目。它的核心思想是:

  1. 使用 createContext 提供全局状态。
  2. 使用 useReducer 管理状态更新逻辑。
  3. 使用 useContext 在组件中访问和操作全局状态。

这种模式简单易用,且不需要引入额外的状态管理库,非常适合 React 项目中需要共享状态的场景。

相关文章:

  • 代码片段 - C#实现多张图片根据重叠部分拼接图像
  • SpringBoot的简单介绍
  • Vue3实战八、路由权限和动态路由
  • 使用 Lua 脚本高效查询 Redis 键的内存占用
  • 【go】slice的浅拷贝和深拷贝
  • Python设计模式:适配模式
  • 2025 年江苏保安员职业资格考试经验分享​
  • starrocks split函数和trino split函数差异性
  • 【正点原子】如何设置 ATK-DLMP135 开发板 eth0 的开机默认 IP 地址
  • Windows RAC 集群故障:表决盘 “失踪” 致无法启动的排查实践
  • Docker部署Jenkins服务
  • ComfyUI模型下载与路径问题解决
  • IAGCN:登上《Nature》的深度学习可解释性情感分析模型突破
  • Appium的学习总结-Inspector参数设置和界面使用(5)
  • 【图像处理基石】什么是ISP色彩管理?
  • Android OpenCV 人脸识别 识别人脸框 识别人脸控件自定义
  • python小整数池和字符串贮存
  • Threejs实现天空盒效果
  • 前端单页应用性能优化全指南:从加载提速到极致体验
  • 《AI大模型趣味实战》智能财务助手系统配套说明:数据报表与指标手册
  • 搜索栏搜索网站?热?文/郑州seo推广优化
  • 网站制作的评价标准/seo搜索排名优化方法
  • 如何做公司的网站建设/推广文案范文100字
  • 潘家园做网站的公司/阳江网站建设
  • 太湖云建站网站建设/2023b站免费推广入口
  • 医疗网站建设怎么样/图片外链