React--》useReducer的讲解与使用

news2025/1/16 18:01:22

目录

useReducer的使用

刨析useReducer参数

useReducer的使用


useReducer的使用

在React函数式组件中,我们可以通过useState()来创建state,这种state创建方式会给我们返回两个东西state和setState()。state用来读取数据,而setState()用来设置修改数据,但这种方法也存在着一些不足,因为所有的修改state方式都必须通过setState()来进行,如果遇到一些复杂度比较高的state时,这种方式就变得有些繁琐了。

为了解决复杂state带来的不便,React为我们提供了一个新的使用state方式,当你的state过于复杂时,你就可以使用对state整合的工具 “Reducer” ,其作用就是将那些和同一个state相关的所有函数都整合到一起,方便在组件中进行调用。

注意:Reducer只适合那些比较复杂的state,对于简单的state使用Reducer只能是徒增烦恼,以下都会用简单的例子来说明Reducer的使用。

刨析useReducer参数

useReducer实际上算是useState的升级版,虽然使用比useState复杂,但其能够应付更加繁琐的应用场景,其接收的参数有三个,接下来将详细刨析useReducer这个Hooks的使用,Reducer和State相同也是一个钩子函数,其语法格式如下:

const [state, dispatch] = useReducer(reducer, initialArg, init?)

数组中第一个参数:用来获取state的值;数组中第二个参数:state修改的派发器,通过派发器可以发送操作state的命令,具体的修改行为将会由另外一个函数执行。

reducer参数:用于指定如何更新状态。它必须函数,应该将状态数据和操作方法作为参数,并且应该返回下一个状态。状态和动作可以是任何类型。即:(state,action) => newState

state:是当前最新的状态值

action:用于告诉reducer当前执行的操作,reducer会根据不同的操作执行不同的逻辑

newState:返回值,返回一个新的state

initialArg参数:用于计算初始状态的值,即为state的初始值,作用和useState()中的值是一样的,它可以是任何类型的值。如何从中计算初始状态取决于下一个init参数。

init参数:可选参数,本质上是一个函数,参数是初始的state,如果传入这个参数的话,那么初始state就是init(initState)的返回结果。通俗来讲就是:应该返回初始状态的初始值设定项函数。如果未指定,则初始状态设置为initialArg。否则,初始状态被设置为调用init(initialArg)的结果。

useReducer的使用

在 官方文档案例 中,已经很明确的告诉我们如何使用useReducer,如下:

官方文通过将reducer函数抽离出来去管理状态的变化,根据传入action的不同返回新的状态,我们在点击按钮时会调用dispatch函数,并传入一个包含type属性的对象即action,这个对象表示将要进行的状态更新操作。

接下来举一个简单的计数器的案例,来比较一下使用Reducer和未使用的区别在哪里。

传统操作State的方法为

import React,{ useState } from 'react'
const App = () => {
  const [num,setNum] = useState(0)
  const addHandler = () =>{ 
    setNum(prenum => prenum + 1)
  }
  const subHandler = () =>{ 
    setNum(prenum => prenum -1)
  }
  return (
    <div style={{fontSize:'30px',padding:'50px'}}>
      <button onClick={addHandler}>加1</button>
      {num}
      <button onClick={subHandler}>减1</button>
    </div>
  )
}
export default App

使用Reducer操作state方法为

import React,{ useReducer } from 'react'
const App = () => {
  // reducer函数 state:当前最新状态值、action:当前执行的操作
  const reducer = (state,action) =>{ 
    switch(action.type){
      case 'ADD':
        return state + 1
      case 'SUB':
        return state - 1
      default:
        return state
    }
  }
  const [num,numDispatch] = useReducer(reducer,0)
  const addHandler = () =>{ 
    numDispatch({type:'ADD'})
  }
  const subHandler = () =>{ 
    numDispatch({type:'SUB'})
  }
  return ( 
    <div style={{fontSize:'30px',padding:'50px'}}>
      <button onClick={addHandler}>加1</button>
      {num}
      <button onClick={subHandler}>减1</button>
    </div>
  )
}
export default App

当然如果是非常简单的state,使用useState是明智的选择,但在某些场景下,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。useReducer会更加适用,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。如下:

import { useReducer } from 'react';

function reducer(state, action) {
  switch (action.type) {
    case 'incremented_age': {
      return {
        name: state.name,
        age: state.age + 1
      };
    }
    case 'changed_name': {
      return {
        name: action.nextName,
        age: state.age
      };
    }
    default:
      return null
  }
}

const initialState = { name: 'Taylor', age: 42 };

export default function App() {
  const [state, dispatch] = useReducer(reducer, initialState);

  function handleButtonClick() {
    dispatch({ type: 'incremented_age' });
  }

  function handleInputChange(e) {
    dispatch({
      type: 'changed_name',
      nextName: e.target.value
    }); 
  }

  return (
    <>
      <input
        value={state.name}
        onChange={handleInputChange}
      />
      <button onClick={handleButtonClick}>
        +1
      </button>
      <p>Hello, {state.name}. You are {state.age} years old</p>
    </>
  );
}

无论是useState还是useReducer,都是为了帮助我们的管理组件的状态 ,但如果你的项目比较复杂,后期要经常加以维护的话,选择useReducer或许是一个不错的选择。

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

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

相关文章

走心Python实战应用:【requests+re 模块】快速下载原shen图片

人生苦短&#xff0c;我用python 这次给大家带来的是模块实战 以便大家理解学习 觉得写的好的话&#xff0c;可以给我多多点赞鸭~ 走心Python实战应用&#xff1a;【requestsre 模块】快速下载原shen图片 一、理解Python requests 模块二、requests 方法三、ruqusets 模块实…

第15章_File类与IO流

第15章_File类与IO流 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. java.io.File类的使用 1.1 概述 File类及本章下的各种流&#xff0c;都定义在java.io包下。 一个File对…

渗透测试成功的8个关键,98%的人都理解错了

01 知道为什么要测试 执行渗透测试的目的是什么&#xff1f;是满足审计要求&#xff1f;是你需要知道某个新应用在现实世界中表现如何&#xff1f;你最近换了安全基础设施中某个重要组件而需要知道它是否有效&#xff1f;或者渗透测试根本就是作为你定期检查防御健康的一项例行…

最新版本 Stable Diffusion 开源 AI 绘画工具之中文自动提词篇

✨ 目录 &#x1f388; 标签生成器&#x1f388; 提示词自动补全 &#x1f388; 标签生成器 由于输入正向提示词 prompt 和反向提示词 negative prompt 都是使用英文&#xff0c;所以对学习母语的我们非常不友好使用网址&#xff1a;https://tinygeeker.github.io/p/ai-prompt…

第05讲:OpenTracing 简介,先有标准后有天

自从 Google Dapper 的论文发布之后&#xff0c;各大互联网公司和开源社区开发的分布式链路追踪产品百花齐放&#xff0c;同时也给使用者带来了一个问题&#xff0c;各个分布式链路追踪产品的 API 并不兼容&#xff0c;如果用户在各个产品之间进行切换&#xff0c;成本非常高。…

Sprinboot聚合项目归夷

1、前言 在创建springboot项目时&#xff0c;都会有一个Main方法。如果将Springboot项目设计成聚合项目时&#xff0c;我们是不是要把所有的子项目都按照Springboot的方式创建呢&#xff1f;如果是会出现什么问题&#xff0c;以及我们怎么解决呢&#xff1f; 如果我们使用maven…

在线画图网站Graph Editor的使用

网站链接 链接 网站介绍 CS Academy是一个在线的算法学习和竞赛的网站&#xff0c;打开网站左侧导航栏中的App目录下有一个可以在线画图的应用Graph Editor&#xff0c;用来画图&#xff08;有向、无向&#xff09;非常好用。 网站使用 网站的界面如下&#xff1a; 左侧为…

Golang每日一练(leetDay0037) 二叉树专题(6)

目录 109. 有序链表转换二叉搜索树 Convert-sorted-list-to-binary-search-tree &#x1f31f;&#x1f31f; 110. 平衡二叉树 Balanced Binary Tree &#x1f31f; 111. 二叉树的最小深度 Minimum Depth of Binary Tree &#x1f31f; &#x1f31f; 每日一练刷题专栏 …

代码随想录算法训练营第五十七天 | 647. 回文子串、516.最长回文子序列

打卡第57天。 今日任务 ● 647. 回文子串 ● 516.最长回文子序列 647. 回文子串 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开…

【云原生进阶之容器】第六章容器网络6.6.1--Cilium网络方案概述

《云原生进阶之容器》专题索引: 第一章Docker核心技术1.1节——Docker综述第一章Docker核心技术1.2节——Linux容器LXC第一章Docker核心技术1.3节——命名空间Namespace第一章Docker核心技术1.4节——chroot技术第一章Docker核心技术1.5.1节——cgroup综述

从入门到精通:带你掌握Python Requests库的全部技能

目录 引言 安装 启动用户管理项目 requests响应 Session请求 为什么Session类可以保持会话 封装requests 引言 Python Requests库是Python语言中最为流行的HTTP客户端库之一。它提供了简单易用的API&#xff0c;让发送HTTP/1.1请求变得异常容易&#xff0c;支持常见的H…

TiDB实战篇-数据导出工具Dumpling

简介 简要使用数据导出工具。 介绍 特点 适用场景 部署 下载 TiDB 社区版 | PingCAP 安装 #解压下载好的安装包 tar -zxvf tidb-community-toolkit-v6.5.0-linux-amd64.tar.gz #进入到文件夹以后解压出dumpling cd tidb-community-toolkit-v6.5.0-linux-amd64 tar -zxvf d…

MySQL中的索引index(超详细)

概念&#xff1a; 在MySQL中&#xff0c;索引&#xff08;index&#xff09;是一种特殊的数据结构&#xff0c;它能够加快数据库中数据的检索速度。索引可以看做是一本书的目录&#xff0c;它提供了一种快速查找数据的方式。 MySQL中的索引是建立在一张表的一列或多列上的&…

开发者社区项目开发流程

项目流程&#xff1a; 项目创建 首先创建一个文件夹&#xff0c;然后找到要创建项目的文件夹 输入CMD 进入小黑窗 输入“vue create 项目名” 创建我们这个项目(其中细节Ctrl左键点击链接见个人博客(99条消息) 创建Vue项目流程_啊唯11的博客-CSDN博客) 2.删除项认文件&#x…

C++命名空间域namespace与域作用限制符: :,cin,cout输入输出简单介绍

TIPS C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库&#xff0c;以及编程范式等C总计63个关键字&#xff0c;C语言32个关键字&#xff0c;具体没有必要先不去管它 域&#xff0c;命名空间域与namespace关键字 cpp需要解决的第一…

Java后端面试题 重难点和被问到没答上来的点(包括java基础、关系型数据库、Redis、计算机网络、Spring、Java多线程、vue等)

以下是我记录的一些重点问题和面试中被问到没答上来的问题&#xff0c;包括java基础、关系型数据库、Redis、计算机网络、Spring、Java多线程、vue 问题目录 1.fail-safe和fail-fast2.四引用3.explain字段重要内容4.maven三大生命周期5.MYSQL 创建修改表6.数据库三范式7.Strin…

华科超算用户手册的学习笔记

1. 资源计费 1.1 费用记账 日期费用&#xff08;上限3000元&#xff09;2023.04.171002023.04.18200总计300 1.2 创建实例时显示项目的余额不足 这是因为项目账户之中目前还没有足够的卡时&#xff1b; Note 这里是因为上次充值的卡时还在田老师的个人账户中&#xff0c;还需…

vue el-table 单机行选中高亮并获取行数据,再次单击取消行选中

1. 效果展示 当没有行被选中时&#xff0c;按钮是不可用的 当有行被选中时&#xff0c;该行高亮&#xff0c;同时按钮可用 再次点击该行&#xff0c;取消高亮&#xff0c;按钮不可用 2. 代码 2.1 组件代码 table设置了highlight-current-row&#xff0c;可以在选中某个数据行…

List集合和Set集合的区别

Collection集合总结 在进行Java开发的时候经常会用到集合&#xff0c;而集合又主要分为两种&#xff1a;Collection单列集合和Map集合。这里主要介绍一下Collection的一些常用子接口的区别。 Collection集合&#x1f62e; 指单列集合&#xff0c;存储的一组对象。 List&#x…

4大方法,教你如何做好项目管理

作为一个项目经理&#xff0c;项目管理是我们日常工作最核心的一项职能。无论是公司的业务开发还是重大项目的推进&#xff0c;都离不开项目管理。然而对于很多初入职场的人来说&#xff0c;项目管理还是一个相当新颖、陌生的领域&#xff0c;因此我今天就来分享一些我在项目管…