react18中实现简易增删改查useReducer搭配useContext的高级用法

useReduceruseContext前面有单独介绍过,上手不难,现在我们把这两个api结合起来使用,该怎么用?还是结合之前的简易增删改查的demo,熟悉vue的应该可以看出,useReducer类似于vuexuseContext类似于vue中的injectprovided,来分析下思路。

实现效果请添加图片描述

代码实现

  • 文件拆解
    在这里插入图片描述
  • 组件入口文件 -> index.js
import { TasksContext, TasksDispatchContext } from "./context";
import { useReducer } from "react";
import { initialTasks } from "./taskLists";
import { taskReucers } from "./tasksReducer";
import AddTask from "./AddTask";
import TaskList from "./TaskList";
function State() {
  const [tasks, dispatch] = useReducer(taskReucers, initialTasks);
  return (
    <TasksContext.Provider value={tasks}>
      <TasksDispatchContext.Provider value={dispatch}>
        <AddTask />
        <TaskList />
      </TasksDispatchContext.Provider>
    </TasksContext.Provider>
  );
}

export default State;
  • AddTask.js
import { useState, useContext } from "react";
import { TasksDispatchContext } from "./context";
let nextId = 3;

function AddTask() {
  let [msg, setMsg] = useState("");
  const dispatch = useContext(TasksDispatchContext);
  const handleSubmit = () => {
    if (!msg) return;
    setMsg("");
    dispatch({
      type: "added",
      task: {
        id: nextId++,
        text: msg,
        done: false,
      },
    });
  };
  const handleChange = (e) => {
    setMsg(e.target.value);
  };
  return (
    <>
      <input type="text" value={msg} onChange={handleChange} />
      <button onClick={handleSubmit}>添加</button>
    </>
  );
}

export default AddTask;

  • context.js文件
import { createContext } from "react";

export const TasksContext = createContext(null);
export const TasksDispatchContext = createContext(null);
  • taskReucers.js
export function taskReucers(state = [], action) {
  switch (action.type) {
    case "added":
      return [...state, action.task];
    case "changed":
      return state.map((task) => {
        if (task.id === action.task.id) {
          return action.task;
        } else return task;
      });
    case "deleted":
      return state.filter((task) => task.id !== action.task.id);
    default:
      throw new Error("Action type not found");
  }
}
  • taskListsData.js
export const initialTasks = [
  { id: 0, text: "Philosopher’s Path", done: true },
  { id: 1, text: "Visit the temple", done: false },
  { id: 2, text: "Drink matcha", done: false },
];
  • TaskList.js
import { useState, useContext } from "react";
import Task from "./Task";
import { TasksContext } from "./context";

function TaskList() {
  const [isEdit, setIsEdit] = useState(false);
  const tasks = useContext(TasksContext);
  const handleChangeValue = (value) => {};
  return (
    <ul>
      {tasks.map((task) => {
        return <Task key={task.id} task={task} />;
      })}
    </ul>
  );
}

export default TaskList;
  • Task.js
import { useState, useContext } from "react";
import { TasksDispatchContext } from "./context";
function Task({ task }) {
  const [isEdit, setIsEdit] = useState(false);
  const dispatch = useContext(TasksDispatchContext);

  let todoContent = "";
  function handleChangeText(e) {
    dispatch({ type: "changed", task: { id: task.id, text: e.target.value } });
  }

  function handleDeleteTask(id) {
    dispatch({ type: "deleted", task: { id } });
  }

  if (isEdit) {
    todoContent = (
      <span>
        <input type="text" value={task.text} onChange={handleChangeText} />
        <button onClick={() => setIsEdit(false)}>完成</button>
      </span>
    );
  } else {
    todoContent = (
      <span>
        <span>{task.text}</span>
        <button onClick={() => setIsEdit(true)}>编辑</button>
      </span>
    );
  }
  return (
    <li>
      {todoContent}
      <button onClick={() => handleDeleteTask(task.id)}>删除</button>
    </li>
  );
}

export default Task;

这样拆解后,明显的业务更加清晰,容易维护了,给后续接手的人一目了然的理解思路。
没有了组件层级之间的繁琐的层层传递数据和方法,代码结构也很清晰了。


进一步的优化业务代码

  • context.js的封装
import { createContext, useReducer } from "react";
import { initialTasks } from "./taskListsData";
import { taskReucers } from "./tasksReducer";

export const TasksContext = createContext(null);
export const TasksDispatchContext = createContext(null);

export default function TasksProvider({ children }) {
  const [tasks, dispatch] = useReducer(taskReucers, initialTasks);
  return (
    <TasksContext.Provider value={tasks}>
      <TasksDispatchContext.Provider value={dispatch}>
        {children}
      </TasksDispatchContext.Provider>
    </TasksContext.Provider>
  );
}
  • 入口文件index.js的优化
import AddTask from "./AddTask";
import TaskList from "./TaskList";
import TasksProvider from "./context";
function State() {
  return (
    <TasksProvider>
      <AddTask />
      <TaskList />
    </TasksProvider>
  );
}

export default State;

这样实现了同样的效果,代码更加精简。
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/892544.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智慧供排水管网在线监测为城市安全保驾护航

一、方案背景 随着城市化进程的不断推进&#xff0c;城市供排水管网作为城市基础设施的关键组成部分&#xff0c;其安全稳定的运行对于确保城市居民的日常生活、工业生产活动以及整个生态环境的健康具有至关重要的作用。近年来&#xff0c;由于各种原因&#xff0c;城市供排水管…

Springboot整合knife4j生成文档

前言 在开发过程中&#xff0c;接口文档是很重要的内容&#xff0c;用于前端对接口的联调&#xff0c;也用于给其他方使用。但是手写相对比较麻烦。 当然也有swagger之类的&#xff0c;但是界面没有那么友好。 官网&#xff1a; 整合步骤 整合依赖 需要根据版本进行&…

深入了解Spring重试组件spring-retry

在我们的项目中&#xff0c;为了提高程序的健壮性&#xff0c;很多时候都需要有重试机制进行兜底&#xff0c;最多就场景就比如调用远程的服务&#xff0c;调用中间件服务等&#xff0c;因为网络是不稳定的&#xff0c;所以在进行远程调用的时候偶尔会产生超时的异常&#xff0…

python之socket网络编程

华子目录 引言什么是socketsocket套接字类型TCP和UDP socket服务端核心组件1.创建socket对象2.绑定地址和端口3.监听连接4.接受连接5.接受client端消息client_sock.revc(1024)6.发送响应给client端6.1client_sock.send()6.2client_sock.sendall() 7.关闭client端连接8.关闭serv…

flutter 使用三方/自家字体

将字体放入assets/fonts下 在pubspec.yaml文件中flutter下添加如下代码&#xff1a; flutter:fonts:- family: MyCustomFontfonts:- asset: assets/fonts/MyCustomFont.ttf 在flutter Text widget中使用字体 import package:flutter/material.dart;void main() > runApp(…

PyQt 入门教程(3)基础知识 | 3.2、加载资源文件

文章目录 一、加载资源文件1、PyQt5加载资源文件2、PyQt6加载资源文件 一、加载资源文件 常见的资源文件有图像与图标&#xff0c;下面分别介绍下加载资源文件的常用方法 1、PyQt5加载资源文件 2、PyQt6加载资源文件 PyQt6版本暂时没有提供pyrcc工具&#xff0c;下面介绍下在不…

js中map,filter,find,foreach的用法介绍

js中map&#xff0c;filter&#xff0c;find&#xff0c;foreach的用法介绍 在 JavaScript 中&#xff0c;数组提供了一些常用的迭代方法&#xff0c;如 map、filter、find 和 forEach&#xff0c;这些方法允许你对数组中的每个元素进行操作&#xff0c;下面是它们的用法和区别…

抖音解压视频素材宝库

在快节奏的生活中&#xff0c;解压视频成为抖音上的热门内容类型&#xff0c;想要制作出精彩的解压视频&#xff0c;优质素材必不可少。今天&#xff0c;为大家推荐几个超棒的抖音解压视频素材网站&#xff0c;让你的创作之路轻松无忧&#xff01; 蛙学网 作为国内知名的短视频…

【Canvas与化学】铁元素图标

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>铁元素图标Draft1</title><style type"text/css"…

域渗透AD 示例场景漏洞 Kerberos Bronze Bit 【CVE-2020-17049】漏洞

背景 漏洞原理 漏洞复现 约束性委派攻击绕过 基于资源的约束性委派攻击绕过 漏洞预防和修复 背景 Kerberos Bronze Bit (CVE-2020-17049) 漏洞是国外安全公司 Netspi 安全研究员Jake Karnes 发现的一个Kerberos安全功能绕过漏洞。该漏洞存在的原因在于KDC在确定Kerberos服…

YoloV10改进:Block改进|使用ContextAggregation模块改善C2f模块|即插即用

摘要 在计算机视觉领域&#xff0c;目标检测与实例分割任务一直是研究的热点。YoloV10作为目标检测领域的佼佼者&#xff0c;凭借其出色的性能和效率赢得了广泛的认可。然而&#xff0c;随着技术的不断进步&#xff0c;如何进一步提升YoloV10的性能成为了我们追求的目标。近期…

Java爬虫之使用Selenium WebDriver 爬取数据

这里写自定义目录标题 Selenium WebDriver简介一、安装部署二、Java项目中使用1.引入依赖2.示例代码 三、WebDriver使用说明1.WebDriver定位器2.常用操作3.使用 cookie4.键盘与鼠标操作 Selenium WebDriver简介 Selenium WebDriver 是一种用于自动化测试 Web 应用程序的工具。…

【实战指南】Vue.js 介绍组件数据绑定路由构建高效前端应用

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

ollama + fastgpt+m3e本地部署

ollama fastgptm3e本地部署 开启WSL更新wsl安装ubuntu docker下载修改docker镜像源开启WSL integration 安装fastgpt先创建一个文件夹来放置一些配置文件用命令下载fastgpt配置文件用命令下载docker的部署文件 启动容器M3E下载ollama下载oneapi配置登录oneapi配置ollama渠道配…

聊聊零基础如何开始学习鸿蒙开发技术

鸿蒙系统是一款分布式操作系统&#xff0c;其适用范围非常广泛&#xff0c;从智能手机到家用电器&#xff0c;再到工业设备&#xff0c;都能找到应用场景。特别是在智能家居领域&#xff0c;鸿蒙系统可以实现不同设备之间的无缝连接和协同工作&#xff0c;提供更加智能和便利的…

Flink On kubernetes

Apache Flink 是一个分布式流处理引擎&#xff0c;它提供了丰富且易用的API来处理有状态的流处理应用&#xff0c;并且在支持容错的前提下&#xff0c;高效、大规模的运行此类应用。通过支持事件时间&#xff08;event-time&#xff09;、计算状态&#xff08;state&#xff09…

数据治理为何如此简单?

欢迎来文末免费获取数据治理相关PPT和文档 引言 随着大数据技术的迅速发展&#xff0c;企业积累的数据量呈现爆炸式增长。有效的数据管理已经成为企业提高决策效率、增强竞争优势的重要手段。在这样的背景下&#xff0c;数据治理逐渐成为企业数据管理中不可或缺的一环。它不仅…

Vivado - Aurora 8B/10B IP

目录 1. 简介 2. 设计调试 2.1 Physical Layer 2.2 Link Layer 2.3 Receiver 2.4 IP 接口 2.5 调试过程 2.5.1 Block Design 2.5.2 释放 gt_reset 2.5.3 观察数据 3. 实用技巧 3.1 GT 坐标与布局 3.1.1 选择器件并进行RTL分析 3.1.2 进入平面设计 3.1.3 收发器布…

【二刷hot-100】day1

目录 1.两数之和 2.字母异位词分组 3.字母异位词分组 4.最长连续序列 5.移动零 6.盛最多水的容器 7.三数之和 8.接雨水 1.两数之和 class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer,Integer> mapnew HashMap<>();for (int i0;i<…

LeakCanary

LeakCanary 文章目录 LeakCanary一、内容1. 使用方法2. 工作原理3.工作流程 参考资料 一、内容 LeakCanary 是在 Android 项目中&#xff0c;用于检测内存泄露&#xff0c;优化性能的工具。 1. 使用方法 本文使用版本为 2.5 版本&#xff0c;相比于 2.0 之前的版本&#xff…