React Hooks之useReducer

news2025/7/18 12:20:44

一、useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init?)
  • useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。
  • 数据结构简单用useState,复杂时用useReducer
  • 简化版的redux
  • 结合context解决跨组件的问题
  • state dispatch默认没有模块化,数据混在一起

  • state或store:数据
  • action:命令
  • reducer: 规定,根据action的type做相应处理返回新的state
  • dispatch: 派发action

二、基本使用

CounterReducer.tsx

// import React, { FC, useState } from 'react' //注释的是使用useState的情况
import React, { FC, useReducer } from 'react'

type StateType = { count: number }
type ActionType = { type: string }

const initialState: StateType = { count: 100 } // 初始值100

// 根据传入的action 返回新的state(不可变数据)
function reducer(state: StateType, action: ActionType) {
  switch(action.type) {
    case 'increment':
      return { count: state.count + 1 }
    case 'decrement':
      return { count: state.count - 1 }
    default:
      throw new Error()
  }
}

const CountReducer:FC = () => {
  // const [count, setCount] = useState(100)
  const [state, dispatch] = useReducer(reducer, initialState)

  return (
    // <>
    //   <p>coint: {count}</p>
    //   <button onClick={() => setCount(count + 1)}>+</button>
    //   <button onClick={() => setCount(count - 1)}>-</button>
    // </>
    <>
      <p>coint: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </>
  )

}

export default CountReducer

三、Todo List By useReducer项目

在这里插入图片描述
使用Context和useReducer实现跨组件通讯
代码地址:点击跳转

store.ts
在这里插入图片描述
reducer.tsx
在这里插入图片描述
List.tsx

import React, { FC, useContext } from 'react'
// import reducer from './reducer'
// import initialState from './store'
import { TodoContext } from '.'

const List:FC = () => {
  // const [state, dispatch] = useReducer(reducer, initialState)
  // const [state, dispatch] = useReducer(reducer, initialState)
  const context = useContext(TodoContext)
  const { state, dispatch } = context
  

  const del = (id: string) => {
    dispatch({
      type: 'delete',
      payload: id
    })
  }
  
  return (
    <>
      <p>list</p>
      <ul>
        {
          state.map(item => {
            return <li key={item.id}>
              <span>{item.title}</span>
              <button onClick={() => del(item.id)}>删除</button>
            </li>
          })
        }
      </ul>
    </>
  )

}

export default List

InputForm.tsx

import React, { FC, ChangeEvent, useState, useContext } from 'react'
// import reducer from './reducer'
// import initialState from './store'
import { nanoid } from 'nanoid'
import { TodoContext } from '.'

const InputForm:FC = () => {
  // const [state, dispatch] = useReducer(reducer, initialState)
  const context = useContext(TodoContext)
  const { state, dispatch } = context

  // 输入框文字
  const [text, setText] = useState('')
  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    setText(event.target.value)
  }
  // 新增todo
  const handleSubmit = (event: ChangeEvent<HTMLFormElement>) => {
    event.preventDefault()
    if (!text.trim()) return
    const newTodo = {
      id: nanoid(5),
      title: text
    }
    dispatch({
      type: 'add',
      payload: newTodo
    })
    setText('')
    
  }

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="new-todo">what needs to be done?</label>
      <br />
      <input id='new-todo' onChange={handleChange} value={text} />
      <button type='submit'>Add #{state.length + 1}</button>
    </form>
  )

}

export default InputForm

index.tsx

import React, { FC, createContext, useReducer } from 'react'
import List from './List'
import InputForm from './InputForm'
import reducer, { ActionType } from './reducer'
import initialState from './store'

export const TodoContext = createContext({
  state: initialState,
  // eslint-disable-next-line
  dispatch: ( action: ActionType ) => {/* 空 */}
})

const Demo:FC = () => {
  const [state, dispatch] = useReducer(reducer, initialState)

  return (
    <TodoContext.Provider value={{ state, dispatch }}>
      <p>Todo list by reducer</p>
      <List />
      <InputForm />
    </TodoContext.Provider>
  )

}

export default Demo

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

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

相关文章

【LeetCode刷题(数据结构与算法)】:有效的括号

首先这里需要用到栈的知识 力扣官方会有相关的栈的实现的接口函数 所以我们这里就直接拷贝一份我们栈的实现的代码 typedef int STDataType;typedef struct Stack {STDataType* a;int top;int capacity; }ST;void STInit(ST* ps) {assert(ps);ps->a NULL;ps->capacity …

自研系统加入license授权(附源码)

1.将ClientDemo&#xff08;源码找作者获取&#xff09;下的cn文件夹的内容导入项目对应的java目录下。 2.将license-config.properties文件导入resources目录下。 3.在项目的pom.xml中添加如下依赖。 <properties><!-- Apache HttpClient --><httpclient>4…

各种语言【Python,Java,Go,Pascal,C++】不解压直接读取压缩包【rar,zip,7z,gz,tar,z...】中文本行

文章目录 &#xff08;零&#xff09;前言&#xff08;一&#xff09;【ZIP】格式&#xff08;1.1&#xff09;Python ⭐️&#xff08;1.2&#xff09;Java ⭐️&#xff08;1.3&#xff09;Golang ⭐️&#xff08;1.4&#xff09;Pascal&#xff08;1.4.1&#xff09;Lazaru…

02. IMX启动方式

02. IMX启动方式 硬件启动方式的选择启动方式的选择串行下载内部BOOT模式 启动设备的选择 启动头文件BOOT ROM做的事情IVT和BOOT Data数据 DCD数据其他的数据 硬件启动方式的选择 启动方式的选择 6ULL是怎么支持从多种外置flash启动程序的? BOOT_MODE0和BOOT_MODE1&#xff…

Ubuntu 18.04 LTS中cmake-gui编译opencv-3.4.16并供Qt Creator调用

一、安装opencv 1.下载opencv-3.4.16的源码并解压 2.在解压后的文件夹内新建文件夹build以及opencv_install 3.启动cmake-gui并设置 sudo cmake-gui&#xff08;1&#xff09;设置界面中source及build路径 &#xff08;2&#xff09;点击configure&#xff0c;选择第一个def…

Linux篇 四、Linux修改用户名

Linux系列文章目录 一、香橙派Zero2设置开机连接wifi 二、香橙派Zero2获取Linux SDK源码 三、香橙派Zero2搭建Qt环境 文章目录 Linux系列文章目录前言一、更改用户名准备二、修改用户名总结 前言 主要讲述了修改普通用户名的过程 一、更改用户名准备 LubanCat 镜像出厂默认是…

算法通关村第18关【黄金】| 继续回溯

1.复原IP地址 思路&#xff1a; 单层for循环start控制开始位置&#xff0c;逐个遍历情况取&#xff0c;附带剪枝&#xff0c;递归返回后进行point回溯 深度递归pointNum三层&#xff0c;确定终止条件 class Solution {List<String> result new ArrayList<>();p…

如何查看前端项目vue版本

&#xff08;1&#xff09;点击package.json文件 &#xff08;2&#xff09;找到dependencies下面的value &#xff08;2&#xff09;查看vue版本 2开头为vue2 3开头为vue3

与 Harbor 构建高效的镜像加速工作流

镜像是容器的基础&#xff0c;如今有很多用户在实践使用 Harbor 作为镜像存储与分发方案&#xff0c;本文介绍了 Harbor 在支持镜像加速方面的能力&#xff0c;以及 Nydus 这种改进的镜像格式&#xff0c;用于解决镜像在网络&#xff0c;存储&#xff0c;端到端可信方面的问题。…

从外网 log4j2 RCE 再到内网组合拳漏洞 CVE-2021-42287、CVE-2021-42278 拿到 DC

网络拓扑 信息搜集 渗透测试第一步当然是信息搜集 拿到 IP192.168.81.151我们先使用nmap对他进行常规TCP端口的扫描 nmap -v -Pn -T3 -sV -n -sT --open -p 22,1222,2222,22345,23,21,445,135,139,5985,2121,3389,13389,6379,4505,1433,3306,5000,5236,5900,5432,1521,1099,5…

银河麒麟服务器x86安装qemu虚拟机,并安装windows server 2019

安装虚拟机 桌面右键&#xff0c;选择在终端中打开 输入下面的脚本 yum install -y virt-viewer virt-v2v libvirt* qemu* virt-manager 等待安装完成 安装成功 打开虚拟机软件 新建虚拟操作系统&#xff0c;以windows server 2019为例 选择镜像 点击前进 点击&#xff1a;是…

C语言实现编一程序显示由符号组成的三角形图案,行数与图形均可自行输入改变

* *** ***** ******* 完整代码&#xff1a; /*编一程序显示由符号组成的三角形图案&#xff0c;行数与图形均可自行输入改变。********* ******* */ #include<stdio.h>int main(){//n表示图案的行数int n;printf("请输入图案的行数:");scanf("%d"…

【数字图像处理笔记】01-数字图像基础

01-数字图像基础 图像类型 黑白(二值)图像 只有黑白两种颜色的图像称为黑白图像或单色图像&#xff0c;图像的每个像素只能是黑或白&#xff0c;没有中间的过渡&#xff0c;故又称为二值图像。 二值图像的像素值只能为0或1&#xff0c;图像中的每个像素值用1位存储。图像矩阵中…

新版外国人永居证身份证读卡器C++开发SDK接口

近期&#xff0c;国家移民管理局对外国人永久居留身份证&#xff08;以下简称永居证&#xff09;进行了升级改造和便利化应用工作&#xff0c;新版永居证将于 2023年 12 月 1 日起正式签发。新版永居证调整了号码规则&#xff0c;改进了信 息储存&#xff0c;优化了图案设计&am…

C++标准模板(STL)- 类型支持 (数值极限,epsilon,round_error,infinity)

数值极限 提供查询所有基础数值类型的性质的接口 定义于头文件 <limits> template< class T > class numeric_limits; numeric_limits 类模板提供查询各种算术类型属性的标准化方式&#xff08;例如 int 类型的最大可能值是 std::numeric_limits<int>::m…

Android查看签名信息系列 · 使用Android Studio获取签名

前言 Android查看签名信息系列 之使用Android Studio获取签名&#xff0c;通过Android Studio自带的gradle来获取签名信息。 优点&#xff1a;此法可查看 MD5、SHA1 等信息。 缺点&#xff1a;升级某个Studio版本后&#xff0c;没有签名任务了&#xff0c;特别不方便。 实现…

简单的对称加密

异或 异或算法的好处便是数A和数B异或后&#xff0c;把结果再和数A异或便可得到B&#xff0c;或者和数B异或可重新得到数据A。利用异或的这个特性可简单实现数据的加密和解密算法。 恺撒密码 恺撒密码的替换方法是通过排列明文和密文字母表&#xff0c;密文字母表示通过将明…

【C++11】智能指针的使用以及模拟实现(shared_ptr,unique_ptr,auto_ptr,weak_ptr)

&#x1f30f;博客主页&#xff1a; 主页 &#x1f516;系列专栏&#xff1a; C ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ &#x1f60d;期待与大家一起进步&#xff01; 文章目录 一、 RAII概念一、auto_ptr1.基本使用2.模拟实现 二、unique_ptr1.基本使用2.模拟实现…

如何禁止在堆上和栈上创建对象

背景 首先需要知道的是&#xff1a; 在栈新建一个对象&#xff0c;不需要调用operator new&#xff0c;创建栈对象时会移动栈顶指针以“挪出”适当大小的空间&#xff0c;然后在这个空间上直接调用对应的构造函数以形成一个栈对象。当对象在栈上创建时&#xff0c;虽然编译器…

Apache Dubbo的主要项目模块

Apache Dubbo的项目结构或者主要项目模块如下所示&#xff1a;