React Hooks之useReducer

2023-11-20

useReducer

官网传送门

前言

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

useState 的替代方案。它接收一个形如 (state, action) => newStatereducer,并返回当前的 state 以及与其配套的 dispatch 方法。(如果你熟悉 Redux 的话,就已经知道它如何工作了。)

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

以下是用 reducer 重写 useState 一节的计数器示例:

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

reducer 的幂等性

reducer本质是一个纯函数,没有任何UI和反作用。这意味着相同的输入(state、action),reducer函数不管执行多少遍始终会返回相同的输出(newState)。所以经过reducer函数很容易推测state的变化,而且也更加容易单元测试。

state 理解

state是当前应用状态对象,能够理解就是咱们熟知的React里面的state

不少时候state可能会是一个复杂的JavaScript对象,针对这种场景咱们可使用ES6的结构赋值:

// 返回一个 newState (newObject)
    function countReducer(state, action) {
        switch(action.type) {
            case 'add':
                return { ...state, count: state.count + 1; }
            case 'sub':
                return { ...state, count: state.count - 1; }
            default: 
                return count;
        }
    }

关于上面这段代码有两个重要的点须要咱们记住:

  1. reducer处理的state对象必须是immutable(不可变的),这意味着永远不要直接修改参数中的state对象,reducer函数应该每次都返回一个新的state object
  2. 既然reducer要求每次都返回一个新的对象,咱们可使用ES6中的解构赋值方式去建立一个新对象,并复写咱们须要改变的state属性,如上例。

但若是咱们的state是多层嵌套,解构赋值实现就很是复杂:

function bookReducer(state, action) {
        switch(action.type) {
            // 添加一本书
            case 'addBook':
                return {
                    ...state,
                    books: {
                        ...state.books,
                        [bookId]: book,
                    }
                };
            case 'sub':
                // ....
            default: 
                return state;
        }
    }

对于这种复杂state的场景推荐使用immerimmutable库解决。

action 理解

action:用来表示触发的行为。

  • type来表示具体的行为类型
  • payload携带的数据
const action = {
        type: 'addBook',
        payload: {
            book: {
                bookId,
                bookName,
                author,
            }
        }
    }
    function bookReducer(state, action) {
        switch(action.type) {
            // 添加一本书
            case 'addBook':
                const { book } = action.payload;
                return {
                    ...state,
                    books: {
                        ...state.books,
                        [book.bookId]: book,
                    }
                };
            case 'sub':
                // ....
            default: 
                return state;
        }
    }

总结

reducer是一个利用action提供的信息,将statepreState转换到newState的一个纯函数,具备一下几个特色:

  • 语法:(state, action) => newState
  • Immutable:每次都返回一个newState, 永远不要直接修改state对象
  • Action:一个常规的Action对象一般有typepayload(可选)组成
  • type: 本次操做的类型,也是 reducer 条件判断的依据
  • payload: 提供操做附带的数据信息

useState + useContext 实现 redux 数据管理效果

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

import React,{useReducer,useContext} from 'react'

const initailState = {
    a:"11111",
    b:"11111"
}

const reducer = (prevState,action)=>{
    let newstate = {...prevState}
    switch(action.type){
        case "change-a":
            newstate.a = action.value
            return newstate
        case "change-b":
            newstate.b = action.value
            return newstate
        default:
            return prevState
    }
    // return prevState
}

const GlobalContext = React.createContext()
export default function App() {
    const [state, dispatch] = useReducer(reducer, initailState)
    
    return (
        <GlobalContext.Provider value={
            {
                state,
                dispatch
            }
        }>
            <div>
                <Child1/>
                <Child2/>
                <Child3/>
            </div>
        </GlobalContext.Provider>
    )
}

function Child1(){
    const {dispatch} = useContext(GlobalContext)
    return <div style={{background:"red"}}>
        <button onClick={()=>{
            dispatch({
                type:"change-a",
                value:"2222222"
            })
        }}>改变a</button>
        <button onClick={()=>{
            dispatch({
                type:"change-b",
                value:"333333"
            })
        }}>改变b</button>
    </div>
}

function Child2(){
    const {state} = useContext(GlobalContext)
    return <div style={{background:"yellow"}}>
        child2-{state.a}
    </div>
}

function Child3(){
    const {state} = useContext(GlobalContext)
    return <div style={{background:"gray"}}>
        child3-{state.b}
    </div>
}

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React Hooks之useReducer 的相关文章

随机推荐

  • 基于Springboot搭建java项目(十五)——RabbitMq的确认机制和延时通知

    RabbitMq的确认机制和延时通知 一 消息发送确认 在RabbitConfig中两个回调函数 一个叫 ConfirmCallback 一个叫 RetrunCallback 1 交换机确认 ConfirmCallback方法 Confir
  • R包实践:lubridate 处理时间数据

    人生有一道难题 那就是如何使一寸光阴等于一寸生命 在数据分析中也有一道难题 那就是如何自如的操作时间数据 R语言的基础包中提供了两种类型的时间数据 一类是Date日期数据 它不包括时间和时区信息 另一类是POSIXct POSIXlt类型数
  • Java实现MD5加密及解密的代码实例

    础 MessageDigest类的使用 其实要在Java中完成MD5加密 MessageDigest类大部分都帮你实现好了 几行代码足矣 对字符串md5加密 param str return import java security Mes
  • DevExpress设置单元格不可编辑,选单元格则选中一行

    DevExpress设置单元格不可编辑 选单元格则选中一行 目的是只展示数据 不提供修改功能 DevexpressGridControl禁止点击单元格修改 设置GridView OptionsBehavior的Editable选项设为Fal
  • JAVA多线程实现-单线程化线程池newSingleThreadExecutor

    JAVA通过Executors提供了四种线程池 单线程化线程池 newSingleThreadExecutor 可控最大并发数线程池 newFixedThreadPool 可回收缓存线程池 newCachedThreadPool 支持定时与
  • char类型数据的取值范围如何确定

    char类型数据是计算机编程语言中只可容纳单个字符的一种基本数据类型 取值范围为 128 127 对于上述概念相信大家都已经很熟悉了 但仍有不少同学对于char类型数据的取值范围抱有疑问 不知道为什么char类型数据的取值范围如何确定 若要
  • 浮点数是否与零相等的判断方法

    1 如何判断单精度浮点数 float a是否等于零 if fabs a lt 1e 6 如果成立 则a等于0 2 如何判断双精度浮点数 double a是否等于零 if fabs a lt 1e 15 如果成立 则a等于0 3 如何判断两个
  • Vue传递数据到后台SpringMVC接收解析返回

    最近在自学vue 开始以为跟angular大同小异 但是真正使用的时候发现还是很多不一样的地方 可能是因为刚刚开始理解的还不够深入O O 下面说说前端jsp怎么和后台交互 后台使用的是springMvc框架 html部分 div table
  • python算法中的机器学习算法之无监督学习知识点(详解)

    目录 学习目标 学习内容 K均值聚类 K Means Clustering 层次聚类 Hierarchical Clustering
  • 带你使用Golang快速构建出命令行应用程序

    在日常开发中 大家对命令行工具 CLI 想必特别熟悉了 如果说你不知道命令工具 那你可能是个假开发 每天都会使用大量的命令行工具 例如最常用的Git Go Docker等 不管是做技术开发还是业务开发 都会有开发命令行程序的场景 例如如果是
  • tomcat升级版本升级

    tomcat升级 1 查看当前tomcat版本 一般tomcat安装在 usr local 下 cd 至apache tomcat xxx bin sh version sh命令 查看版本信息 2 下载需要的tomcat安装包 下载网址 h
  • JavaScript 分支结构语句

    JavaScript 分支结构语句 1 if语句 2 if else语句 双分支语句 3 if else if 语句 多分支语句 4 三元表达式 5 switch语句 语句 也称为流控制语句 通常使用一或多个关键字完成既定的任务 语句可以简
  • 使用Export2Excel.js导出excel

    使用Export2Excel js导出excel 安装依赖 下载Export2Excel js文件 使用 安装依赖 npm install S file saver npm install S xlsx npm install D scri
  • python实现石头剪刀布_利用python实现和电脑玩石头剪刀布

    先说一下石头剪刀布的游戏规则 1 石头 胜 剪刀 2 剪刀 胜 布 3 布 胜 石头 石头 1 剪刀 2 布 3 其中电脑是随机输出1 3之间的整数 玩家手动输入 了解一下python的随机处理 下面上代码 导入随机工具包 importra
  • java8中List根据某一字段去重

    实体类 package test public class User private String userid private String username private String age private String addre
  • sql自带的函数

    1 字符串函数 length 字符串的长度 select LEN 思敏sb 全大写 全小写 select UPPER abCD select LOWER abCD 取左边 右边指定位数的字符串 select LEFT 思敏好傻 2 sele
  • CentOS 6.0 缺少 mcrypt 扩展 解决办法

    解决办法 安装php mcrypt libmcrypt libmcrypt devel这三个库文件1 安装第三方yum源 默认yum源里面没有这几个库文件 不能使用yum安装 wget http www atomicorp com inst
  • CSS 资源大全中文版

    预处理器 更快地编译 CSS GCSS 一个用GO语言编写的CSS预处理器 官网 LESS 向下兼容CSS并为当前的CSS增加额外的功能 官网 Myth 只用写纯CSS而不用担心浏览器加载缓慢 官网 PCSS 一个用Python语言编写的C
  • 虚拟机安装windows7的ISO镜像文件

    链接 https pan baidu com s 1stvzfq9UQFjlwAm4NzPpCg 提取码 wf67 复制这段内容后打开百度网盘手机App 操作更方便哦
  • React Hooks之useReducer

    useReducer 官网传送门 前言 const state dispatch useReducer reducer initialArg init useState 的替代方案 它接收一个形如 state action gt newSt