🚀通过任务管理应用了解 React Context

使用任务管理应用程序理解 React Context

React Context 提供了一种在组件树中共享诸如 state 和 dispatch 之类的值的方法,而无需 prop 钻取。在本文中,我们将介绍如何在 **任务管理应用** 中实现 React Context,以高效地管理任务。

为什么选择 React Context?

当通过多层组件传递 props 时,Prop 钻取是一个常见问题。React Context 通过允许您定义任何组件都可以直接访问的全局状态来帮助解决此问题。

我们的项目:任务管理应用程序

我们将构建一个简单的**任务管理应用程序**,用户可以:

  • 添加任务
  • 编辑任务
  • 将任务标记为完成/未完成
  • 删除任务
  • 让我们深入研究一下具体实现。

    设置上下文

    首先,创建一个上下文来管理我们的任务。

    定义任务类型和上下文

    在 `TaskContext.tsx` 中,定义 `TaskType`、初始状态和上下文设置。

    import React, { createContext, useReducer, PropsWithChildren } from "react";
    
    export interface TaskType {
        id: number;
        text: string;
        done: boolean;
    }
    
    type Action =
        | { type: "added"; id: number; text: string }
        | { type: "changed"; task: TaskType }
        | { type: "deleted"; id: number };
    
    interface TaskContextType {
        tasks: TaskType[];
        dispatch: React.Dispatch;
    }
    
    const initialState: TaskType[] = [];
    
    const TaskContext = createContext(undefined);
    
    function taskReducer(tasks: TaskType[], action: Action): TaskType[] {
        switch (action.type) {
            case "added":
                return [...tasks, { id: action.id, text: action.text, done: false }];
            case "changed":
                return tasks.map((task) =>
                    task.id === action.task.id ? action.task : task
                );
            case "deleted":
                return tasks.filter((task) => task.id !== action.id);
            default:
                throw new Error(`Unhandled action type: ${action.type}`);
        }
    }
    
    export function TaskProvider({ children }: PropsWithChildren) {
        const [tasks, dispatch] = useReducer(taskReducer, initialState);
    
        return (
            
                {children}
            
        );
    }
    
    export function useTaskContext() {
        const context = React.useContext(TaskContext);
        if (!context) {
            throw new Error("useTaskContext must be used within a TaskProvider");
        }
        return context;
    }

    在组件中使用 Context

    现在上下文已经准备好了,让我们在我们的应用程序中使用它。

    添加任务组件

    import React, { useState } from "react";
    import { useTaskContext } from "./TaskContext";
    
    export function AddTask() {
        const { dispatch } = useTaskContext();
        const [text, setText] = useState("");
    
        const handleAddTask = () => {
            if (text.trim()) {
                dispatch({ type: "added", id: Date.now(), text });
                setText(""); // Clear the input
            }
        };
    
        return (
            
    setText(e.target.value)} placeholder="Add a new task" />
    ); }

    任务组件

    import React, { useState } from "react";
    import { TaskType, useTaskContext } from "./TaskContext";
    
    interface TaskProps {
        task: TaskType;
    }
    
    export function Task({ task }: TaskProps) {
        const { dispatch } = useTaskContext();
        const [isEditing, setIsEditing] = useState(false);
        const [editText, setEditText] = useState(task.text);
    
        const handleSave = () => {
            dispatch({ type: "changed", task: { ...task, text: editText } });
            setIsEditing(false);
        };
    
        return (
            
    dispatch({ type: "changed", task: { ...task, done: !task.done }, }) } /> {isEditing ? ( <> setEditText(e.target.value)} /> ) : ( <> {task.text} )}
    ); }

    集成组件

    最后,将所有内容整合到“App.tsx”中。

    import React from "react";
    import { TaskProvider } from "./TaskContext";
    import { AddTask } from "./AddTask";
    import { Task } from "./Task";
    
    export default function App() {
        return (
            
                

    Task Management App

    {/* Use the context to map tasks */}
    ); } function TaskList() { const { tasks } = useTaskContext(); return (
    {tasks.map((task) => ( ))}
    ); }

    结论

    通过使用 React Context,我们消除了在任务管理应用中进行 prop 钻取的需要。`TaskProvider` 封装了状态管理,可以轻松扩展更多功能。

    这种结构可扩展、可维护,并确保关注点的清晰分离。React Context 与 `useReducer` 相结合是管理 React 应用程序中全局状态的强大模式。