7.react useReducer使用与常见问题

news2025/7/1 17:19:57

useReducer函数

1. useState的替代方案.接收一个(state, action)=>newState的reducer,
并返回当前的state以及与其配套的dispatch方法

2. 在某些场景下,useReducer会比useState更加适用,例如state逻辑较为复杂,
且**包含多个子值**,或者下一个state依赖于之前的state等

清楚useReducer场景?
与useState区别?
不足之处,只能处理同步
如何实现异步,提供了两个案例?

1. 用useState做登录

一组响应式数据有关联关系,可以做成一个整体,使用useReducer将其作为一个整体实现

<body>
  <div id="app"></div>
  <script type="text/babel">
    let app = document.querySelector('#app');
    let root = ReactDOM.createRoot(app);
    let { useState } = React;

    // 用useState做登录
    // >  一组响应式数据有关联关系,可以做成一个整体,使用useReducer将其作为一个整体实现
    let Welcome = (props) => {  
      const [ isLogin, setLogin ] = useState(true);
      const [ isLogout, setLogout ] = useState(false);
      const handleLogin= () => {
        setLogin(true);
        setLogout(false);
      }

      const handleLogout= () => {
        setLogout(true);
        setLogin(false);
      }
      return (
        <div>
         {
          isLogin?
          <button onClick={handleLogout}>登出</button>:
          <button onClick={handleLogin}>登录</button>
         }
        </div>
      );
    }
    
    let element = (
      <Welcome />
    );
    root.render(element);
  </script>
</body>

2. 改为useReducer

<body>
  <div id="app"></div>
  <script type="text/babel">
    /* 
    useReducer改写
    */

    let app = document.querySelector('#app');
    let root = ReactDOM.createRoot(app);
    let { useReducer } = React;


    let loginState = {
      isLogin: true,
      isLogout: false
    }

    // 不足: 处理同步action
    let loginReducer = (state, action) => {
      switch (action.type) {
        case 'login':
          return { isLogin: true, isLogout: false }
        case 'logout':
          return { isLogin: false, isLogout: true }
        default:
          throw new Error()
      }
    }
    // 用useReducer做登录
    // > 根据类型,决定不同的state处理变化
    let Welcome = (props) => {
      const [state, loginDispatch] = useReducer(loginReducer, loginState);
      const handleLogin = () => {
        loginDispatch({ type: 'login' })
      }

      const handleLogout = () => {
        loginDispatch({ type: 'logout' })
        // loginDispatch({ type: 'logout' ,payload:''})
      }
      return (
        <div>
          {
            state.isLogin ?
              <button onClick={handleLogout}>登出</button> :
              <button onClick={handleLogin}>登录</button>
          }
        </div>
      );
    }

    let element = (
      <Welcome />
    );
    root.render(element);
  </script>
</body>

不足

useReduer只处理同步请求,对异步请求如何处理?
https://zhuanlan.zhihu.com/p/114367502
在这里插入图片描述

在这里插入图片描述

3.1 异步封装

组件页面
const init = { dataList:[] };//初始化dataState
 
const [state,dispatch] = useReducer(reducer,init);
 
useEffect(() => {
    //发送网络请求
    axios.get("/user?ID=123").then(res => {
        dispatch({
            type:ACTION_TYPE.GETDATA,
            payload:res.data //后端返回的数据
        })
    })
},[]);
 
//使用 state.dataList 渲染页面
在reducer页面

function reducer(state,action){
    switch(action.type){
        case "getData":
            return { //根据需求对数据做出操作,这里将返回的数据与初始化的数据合并
                ...state,
                dataList:action.payload 
            };
}    
 
export default reducer;

3.2 异步封装

初始化直接执行获取数据

import React, { useEffect, useState, useReducer } from "react";
import ReactDom from "react-dom";
import $ from "jquery";

const useProduct = () => {
  const [data, dispatch] = useReducer((state, action) => {
    switch (action.type) {
      case "a":
        return action.value;
      default:
        return [];
    }
  }, []);

  useEffect(() => {
    $.ajax({
      url: "http://suggest.taobao.com/sug?code=utf-8&q=袜子",
      dataType: "jsonp",
      jsonp: "callback",
      success: (data) => {
        dispatch({
          type: 'a',
          value: data.result
        });
      },
      error: data => dispatch({type: 'error', msg: data})
    });
  }, []);

  return data;
};

const Index = () => {
  const data = useProduct();

  return <>{data.length}</>;
};

ReactDom.render(<Index />, document.getElementById("root"));

官网:
1. https://zh-hans.legacy.reactjs.org/docs/hooks-reference.html#usereducer

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

postgresql-日期函数

postgresql-日期函数 日期时间函数计算时间间隔获取时间中的信息截断日期/时间创建日期/时间获取系统时间CURRENT_DATE当前事务开始时间 时区转换 日期时间函数 PostgreSQL 提供了以下日期和时间运算的算术运算符。 计算时间间隔 age(timestamp, timestamp)函数用于计算两…

Uniapp笔记(五)uniapp语法4

本章目标 授权登录【难点、重点】 条件编译【理解】 小程序分包【理解】 一、授权登录 我的模块其实是两个组件&#xff0c;一个是登录组件&#xff0c;一个是用户信息组件&#xff0c;根据用户的登录状态判断是否要显示那个组件 1、登录的基本布局 <template><…

LLMs NLP模型评估Model evaluation ROUGE and BLEU SCORE

在整个课程中&#xff0c;你看到过类似模型在这个任务上表现良好&#xff0c;或者这个微调模型在性能上相对于基础模型有显著提升等陈述。 这些陈述是什么意思&#xff1f;如何形式化你的微调模型在你起初的预训练模型上的性能改进&#xff1f;让我们探讨一些由大型语言模型开…

【Linux】【驱动】注册字符设备号

【Linux】【驱动】注册字符设备号 1. 绪论1 、静态分配设备号2、动态分配设备号3、注销设备号 2 实现的代码3 加载驱动程序 1. 绪论 在之前杂项设备的时候&#xff0c;设备号是固定的&#xff0c;字符设备就需要自己去申请设备号了&#xff0c; 申请设备号有两个方式&#xff…

2024年Android应用开发的6大框架

2024年Android应用开发的6大Framwork 2024年Android应用开发的6大框架&#xff0c;影响移动应用开发领域&#xff0c;改变应用的创建和用户使用方式。随着移动应用市场不断发展&#xff0c;对灵活和高效框架的需求也在增加。这些框架为开发人员提供资源和工具&#xff0c;构建…

手写RPC框架--1.介绍与网络传输

介绍与网络传输 0.介绍a.什么是rpcb.rpc的通信流程 1.网络传输a.零拷贝1) 零拷贝的概念2) Netty的零拷贝 b.IO多路复用c.Netty入门1) netty中的helloworld d.封装报文1) 协议结构2) 模拟封装报文 e.序列化f.压缩和解压缩 0.介绍 a.什么是rpc rpc 的全称是 Remote Procedure C…

S905L3A(M401A)拆解, 运行EmuELEC和Armbian

关于S905L3A / S905L3AB S905Lx系列没有公开资料, 猜测是Amlogic用于2B的芯片型号, 最早的 S905LB 是 S905X 的马甲, 而这个 S905L3A/S905L3AB 则是 S905X2 的马甲, 因为在性能评测里这两个U的得分几乎一样. S905L3A/S905L3AB 和 S905X2, S905X3 一样 GPU 是 G31, 相比前一代的…

【Linux】深入理解文件操作

文章目录 初次谈论文件重温C语言文件操作系统文件操作接口openwriteread 再次谈论文件文件描述符文件描述符的分配规则 重定向什么是重定向重定向的本质系统调用接口实现重定向<、>、>> 初次谈论文件 开始之前先谈论一下关于文件的一些共识性问题。 一个文件可以…

(笔记一)利用open_cv在图像上进行点标记,文字注记,画圆、多边形、椭圆

&#xff08;1&#xff09;CV2中的绘图函数&#xff1a; cv2.line() 绘制线条cv2.circle() 绘制圆cv2.rectangle() 绘制矩形cv2.ellipse() 绘制椭圆cv2.putText() 添加注记 &#xff08;2&#xff09;注释 img表示需要绘制的图像color表示线条的颜色&#xff0c;采用颜色矩阵…

联想电脑装系统无法按F9后无法从系统盘启动的解决方案

开机时按F9发现没有加载系统盘. 打开BIOS设置界面&#xff0c;调整设置如下: BOOT MODE: Legacy Support.允许legacy方式boot. BOOT PRIORITY: Legacy First. Legacy方式作为首选的boot方式. USB BOOT: ENABLED. 允许以usb方式boot. Legacy: 这里设置legacy boot的优先级,…

保姆级教程:从0到1使用Stable Diffusion XL训练LoRA模型 |【人人都是算法专家】

Rocky Ding 公众号&#xff1a;WeThinkIn 写在前面 【人人都是算法专家】栏目专注于分享Rocky在AI行业中对业务/竞赛/研究/产品维度的思考与感悟。欢迎大家一起交流学习&#x1f4aa; 大家好&#xff0c;我是Rocky。 Rocky在知乎上持续撰写Stable Diffusion XL全方位的解析文章…

HTML之VSCode简单配置与创建

目录 插件下载 然后输入源码&#xff1a; 使用 效果 插件下载 下载这个插件后可以直接运行&#xff1a; 然后创建一个文件&#xff1a; 然后输入源码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"…

渗透测试工具ZAP入门教程(1)-安装和快速开始

介绍 ZAP Zed Attack Proxy&#xff08;ZAP&#xff09;是一个免费的开源渗透测试工具&#xff0c;在 软件安全项目 &#xff08;SSP&#xff09;。ZAP 专为测试 Web 应用程序而设计&#xff0c;既灵活又可扩展。 ZAP的核心是所谓的“中间人代理”。它位于测试人员的浏览器和…

【算法训练-双指针】最长无重复子串(数组)

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是最长无重复子串或最长无重复子数组&#xff0c;这类题目出现频率还是很高的。 最长无重复子数组 先来看看数组数据结构的题目 题干 输入&#…

Shiro认证框架

目录 概述 认证授权及鉴权 Shiro框架的核心组件 基本流程 spring bootshiromybatisPlus...实现用户登录 step1:准备工作 (1)坐标 (2)连接数据库 (3)JavaBean (4)dao数据访问层 (5)密码工具类 DigestsUtil (6)配置类 step2&#xff1a;认证功能 step3:授权鉴权 概述…

11. 网络模型保存与读取

11.1 网络模型保存(方式一) import torchvision import torch vgg16 torchvision.models.vgg16(pretrainedFalse) torch.save(vgg16,"./model/vgg16_method1.pth") # 保存方式一&#xff1a;模型结构 模型参数 print(vgg16) 结果&#xff1a; VGG((feature…

飞腾FT-2000/4、D2000 log报错指导(2)

在爱好者群中遇见了很多的固件问题,这里总结记录了大家的交流内容和调试心得。主要是飞腾桌面CPU FT-2000/4 D2000相关的,包含uboot和UEFI。希望对大家调试有所帮助。 这个专题会持续更新,凑够一些就发。 12 UEFI现象:主板启动时串口信息停在 s3 flag form ec 处,如下图所…

局域网中电脑共享文件给手机

学习资源&#xff1a; 局域网共享&#xff1a;这样设置&#xff0c;你可以轻松拷贝任何电脑的文件。_哔哩哔哩_bilibili 可以实现什么效果&#xff1f; 连接同一个WIFI&#xff0c;电脑端为服务端&#xff0c;提供共享文件&#xff0c;手机是客户端&#xff0c;可以读取服务端…

Java-泛型

文章目录 Java泛型什么是泛型&#xff1f;在哪里使用泛型&#xff1f;设计出泛型的好处是什么&#xff1f;动手设计一个泛型泛型的限定符泛型擦除泛型的通配符 结论 Java泛型 什么是泛型&#xff1f; Java泛型是一种编程技术&#xff0c;它允许在编译期间指定使用的数据类型。…

Leetcode:238. 除自身以外数组的乘积【题解超详细】

纯C语言实现&#xff08;小白也能看明白&#xff09; 题目 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数…