React 解释常见的 hooks: useState / useRef / useContext / useReducer
前言
如果对
re-render
概念还不清楚,建议先看 React & 理解 re-render 的作用、概念,并提供详细的例子解释 再回头看本文。
如果对 React 基础语法还不熟练,建议先看 React & JSX 日常用法与基本原则 再回头看本文。
useState
useState
可以用来声明响应式数据。
使用案例:
import ReactDOM from 'react-dom/client';
import { useState } from 'react';
const root = ReactDOM.createRoot(document.getElementById("root"));
const App = () => {const [name, setName] = useState('Jack')return <><div>My name is {name}</div><button onClick={() => setName('John')}>Change my name</button></>
}
root.render(<App />
);
效果:
注意,state 更新采用异步执行 re-render,因此控制台打印的值仍然是旧的。
若希望能够在 state 变更后马上拿到最新的值,有两种方案:
- 使用临时变量存储要变更的值:
// ...
const onChangeName = () => {const tempName = 'John'setName(tempName)console.log('My current name is', tempName)}
// ...
- 使用 useRef,下面会讲。
useRef
useRef
也是声明响应式数据的一种方式,与 useState 不同的是,它可以不受 re-render 的约束,在更新数据后能立刻访问最新的值。
使用案例:
import ReactDOM from 'react-dom/client';
import { useRef } from 'react';
const root = ReactDOM.createRoot(document.getElementById("root"));
const App = () => {const name = useRef('Jack')const onChangeName = () => {name.current = 'John'console.log('My current name is', name.current)}return <><div>My name is {name.current}</div><button onClick={onChangeName}>Change my name</button></>
}
root.render(<App />
);
效果:
可以看出 useRef
与 useState
是两种相反的结果,控制台为最新,视图为旧。
在不强调视图的情况可以考虑用 useRef
,比如异步回调获取最新数据的场景。
useReducer
useReducer
是 useState
的进阶版,当 useState 操作逻辑变得复杂时,可以将它们提升为 useReducer
的书写方式 ,提高可读、维护性。
下面是 useEffect VS useReducer 相同功能的对比图:
useReducer
通过 switch
声明式结构,我们能一眼就能看出每个 type 都做了哪些事。
从对比图看,虽然没能展现 useReducer
的优势,但我们只要理解它的逻辑处理结构就行了,
多一种选择,何乐而不为呢。
在 useState 处理少量逻辑的情况下优先 useState
,反之 useReducer
。
案例代码:
import ReactDOM from 'react-dom/client';
import { useReducer } from 'react';
const root = ReactDOM.createRoot(document.getElementById("root"));const todoReducer = (state, action) => {switch (action.type) {case 'add':return {...state,todos: [...state.todos,Math.floor(Math.random() * 1000)]}case 'remove':return {...state,todos: state.todos.splice(state.index)}default:return state}
}
const App = () => {const [state, dispatch] = useReducer(todoReducer, { todos: [] })return <><header>Todos</header><button onClick={() => dispatch({ type: 'add' })}>Add todo</button><button onClick={() => dispatch({ type: 'remove' })}>Remove todo</button><ul>{state.todos.map((todo) => (<li key={todo}>{todo}</li>))}</ul></>
}
root.render(<App />
);
参数解释:useReducer(reducer, initialArg, init?)
- 第一个参数是一个 handler,即要处理数据的函数。
- 第二个参数是默认值,和 useState(xx) 的第一个参数一样。
- 第三个参数是一个 useMemo 回调函数(可选项),它可以缓存第二个参数的数据,避免 re-render 重复定义默认值。
useReducer 返回的 state
/ dispatch
表示:
- state 获取我们的数据。
- dispatch 触发 handler 函数
提示:掌握了
useReducer
等于学会了react-redux
框架,它与 useReducer 的区别仅仅多了一层全局缓存的含义,对 react-redux 感兴趣的可参考:
React & 用一个简单案例体验一遍 React-dom & React-router & React-redux 全家桶
useContext
useContext
可以解决多层组件传递 props 数据的问题,如果你用过 Vue 的 provide/inject 函数,那你也就会了,它们俩的作用&概念是一致的。
案例代码:
import ReactDOM from 'react-dom/client';
import { createContext, useContext, useState } from 'react';
const root = ReactDOM.createRoot(document.getElementById("root"));
const Profile = () => {const userInfo = useContext(UserInfoContext)return <><label>Name: {userInfo.name}</label><br /><label>Age: {userInfo.age}</label><br /><label>Hobbies: {userInfo.hobbies.map(hobby => <span key={hobby}>{hobby} </span>)}</label></>
}
const ShoppingCart = () => {const userInfo = useContext(UserInfoContext)return <><footer>Shopping Cart:</footer><ul>{userInfo.carts.map((cart) => <li key={cart}>{cart}</li>)}</ul>Total num: {userInfo.carts.length }</>
}const UserInfoContext = createContext(null)
const App = () => {const [userInfo] = useState({name: 'Jack',age: 30,hobbies: ['Running', 'Painting'],carts: ['Dog toy', 'Cup']})return <><UserInfoContext.Provider value={userInfo}><Profile/><ShoppingCart/></UserInfoContext.Provider></>
}
root.render(<App />
);
效果:
useMemo / useCallback
useMemo
可以缓存非响应式数据,避免 re-render
的问题。
useCallback
可以缓存函数,避免 re-render
的问题。
对于函数缓存,虽然 useMemo 也能实现,但还是得额外嵌套一层函数,因此官方建议使用
useCallback
。
俩钩子的用法在 React & 理解 re-render 的作用、概念,并提供详细的例子解释 都有详细的解释,这里不再赘述。
完!
相关文章:
React 解释常见的 hooks: useState / useRef / useContext / useReducer
前言 如果对 re-render 概念还不清楚,建议先看 React & 理解 re-render 的作用、概念,并提供详细的例子解释 再回头看本文。 如果对 React 基础语法还不熟练,建议先看 React & JSX 日常用法与基本原则 再回头看本文。 useState useS…...
telnet发送邮件教程:安全配置与操作指南?
telnet发送邮件的详细步骤?怎么用telnet命令发邮件? 尽管现代邮件客户端和服务器提供了丰富的功能和安全性保障,但在某些特定场景下,了解如何使用telnet发送邮件仍然是一项有价值的技能。AokSend将详细介绍如何安全配置和操作tel…...
超强大的 Nginx 可视化管理工具
今天给大家介绍一款 Nginx 可视化管理界面,非常好用,小白也能立马上手。 nginx-proxy-manager 是一个反向代理管理系统,它基于 NGINX,具有漂亮干净的 Web UI。还可以获得受信任的 SSL 证书,并通过单独的配置、自定义和…...
Android 安装应用-提交阶段之后剩下的操作
它的实现代码在executePostCommitSteps(commitRequest)中,看一下它的代码: /*** On successful install, executes remaining steps after commit completes and the package lock* is released. These are typically more expensive or require calls t…...
buuctf [ACTF2020 新生赛]Include
学习笔记。 开启靶机。 进入靶场: 我们跟进 tips瞅瞅: 额,纯小白,能想到的就是先F12看看,在CTRLu、以及抓包。 得,不会了,看wp呗,不会死磕没脑子0,0? 参考:…...
JS使用MutationObserver接口来监听DOM的更新
在JavaScript中,可以使用MutationObserver接口来监听DOM的更新。以下是一个使用MutationObserver的示例代码,它监听一个DOM节点的变化,并在变化发生时输出信息 // 选择目标节点 const targetNode document.getElementById(some-id);// 创建…...
图解C#高级教程(三):泛型
本讲用许多代码示例介绍了 C# 语言当中的泛型,主要包括泛型类、接口、结构、委托和方法。 文章目录 1. 为什么需要泛型?2. 泛型类的定义2.1 泛型类的定义2.2 使用泛型类创建变量和实例 3. 使用泛型类实现一个简单的栈3.1 类型参数的约束3.2 Where 子句3…...
240930_CycleGAN循环生成对抗网络
240930_CycleGAN循环生成对抗网络 CycleGAN,也算是笔者记录GAN生成对抗网络的第四篇,前三篇可以跳转 240925-GAN生成对抗网络-CSDN博客 240929-DCGAN生成漫画头像-CSDN博客 240929-CGAN条件生成对抗网络-CSDN博客 在第三篇中,我们采用了p…...
ide 使用技巧与插件推荐
ide 使用技巧与插件推荐 一、IDE 使用技巧 1. 快捷键 掌握常用快捷键: Windows: 使用 Ctrl、Alt 和 Shift 的组合。 Mac: 使用 Cmd、Option 和 Shift。 常用快捷键示例: VS Code: Ctrl P: 快速打开文件。 Ctrl Shift P: 打开命令面板。 Ctrl /…...
【node】 cnpm|npm查看、修改镜像地址操作 换源操作
【node】 cnpm|npm查看、修改镜像地址操作 换源操作 安装完node后 npm 1.查看当前npm信息 npm -v2.查看当前的镜像源 npm config get registry3.如果需要淘宝镜像源,修改当前的镜像源为淘宝镜像源 registry https://registry.npm.taobao.org弃用 npm config se…...
大数据-152 Apache Druid 集群模式 配置启动【下篇】 超详细!
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...
IDE 使用技巧与插件推荐全面指南
目录 目录 常用IDE概述 Visual Studio Visual Studio Code IntelliJ IDEA PyCharm Eclipse IDE 使用技巧 通用技巧 Visual Studio 专属技巧 Visual Studio Code 专属技巧 IntelliJ IDEA 专属技巧 插件推荐 Visual Studio 插件 Visual Studio Code 插件 IntelliJ…...
java-快速将普通main类变为javafx类,并加载自定义fxml
java-快速将普通main类变为javafx类,并加载自定义fxml 前提步骤1. 普通类继承Application2. 实现main方法3. 写一个controller4. 写一个fxml文件5. 写start方法加载fxml6. 具体代码7. 运行即可 前提 使用自带javafx的jdk,这里使用的是jdk1.834ÿ…...
数据结构之——单循环链表和双向循环链表
一、单循环链表的奥秘 单循环链表是一种特殊的链表结构,它在数据结构领域中具有重要的地位。其独特的循环特性使得它在某些特定的应用场景中表现出强大的优势。 (一)结构与初始化 单循环链表的结构由节点组成,每个节点包含数据域…...
Git Stash: 管理临时更改的利器
Git 是一个非常强大的版本控制系统,它不仅帮助我们管理代码的版本,还提供了许多实用的功能来优化我们的工作流程。今天,我们要介绍的是 Git 中的一个非常实用的功能——git stash。 什么是 Git Stash? 在开发过程中,…...
ELK--收集日志demo
ELK--收集日志demo 安装ELK日志收集配置启动容器springboot配置测试 之前项目多实例部署的时候,由于请求被负载到任意节点,所以查看日志是开多个终端窗口。后来做了简单处理,将同一项目的多实例日志存入同一个文件,由于存在文件锁…...
Redis的主要特点及运用场景
Redis的主要特点及运用场景 Redis(Remote Dictionary Server)是一个开源的高性能键值对(key-value)数据库。它支持多种类型的数据结构,如字符串(strings)、散列(hashes&…...
与我免费ai书童拆解《坚持》创作历程
插科打诨的海侃胡闹,调侃舒展《坚持》诗创的灵魂盛宴之旅。 (笔记模板由python脚本于2024年09月30日 19:11:42创建,本篇笔记适合喜欢python和诗歌的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free&#x…...
昇思MindSpore进阶教程--下沉模式
大家好,我是刘明,明志科技创始人,华为昇思MindSpore布道师。 技术上主攻前端开发、鸿蒙开发和AI算法研究。 努力为大家带来持续的技术分享,如果你也喜欢我的文章,就点个关注吧 正文开始 昇腾芯片集成了AICORE和AICPU等…...
Hive SQL业务场景:连续5天涨幅超过5%股票
一、需求描述 现有一张股票价格表 dwd_stock_trade_dtl 有3个字段分别是: 股票代码(stock_code), 日期(trade_date), 收盘价格(closing_price) 。 请找出满足连续5天以上(含)每天上涨超过5%的股票,并给出连续满足…...
Java 如何从图片上提取文字
生活中我们可能会遇到想从图片上直接复制上边的文字,该如何获取呢,接下来看看如何使用Java程序实现从图片中读取文字。 实现过程 1、引入Tess4J 依赖 <!--Tess4J 依赖--> <dependency><groupId>net.sourceforge.tess4j</groupId…...
C#进阶-读写Excel常用框架及其使用方式
目录 一、MiniExcel开源框架(推荐) 1、写/导出 方式一 方式二 多表创建 更改配置 特性使用 CSV尾行新增行 CSV、XLSX互转 2、读/导入 简单示例 二、NPOI开源框架 一、MiniExcel开源框架(推荐) 添加NuGet包MiniExcel…...
Python爬虫lxml模块安装导入和xpath基本语法
lxml模块是Python的一个解析库,主要用于解析HTML和XML文件。 一、安装导入 使用包管理器安装,在cmd下或编辑器下的控制台,运行: pip install lxml 导入: from lxml import etree 二、xpath基础知识 XPath&#…...
python魔法(python高级magic方法进阶)
python特殊方法(magic方法也叫魔术方法) 魔法方法是python的内置函数,一般以双下划线开头和结尾, 构造和初始化 每个人都知道一个最基本的魔术方法, init 。 通过此方法我们可以定义一个对象的初始操作。 然而,当我调用 x S…...
【论文笔记】Flamingo: a Visual Language Model for Few-Shot Learning
🍎个人主页:小嗷犬的个人主页 🍊个人网站:小嗷犬的技术小站 🥭个人信条:为天地立心,为生民立命,为往圣继绝学,为万世开太平。 基本信息 标题: Flamingo: a Visual Langu…...
问:JAVA阻塞队列实现类及最佳实践?
在多线程编程中,阻塞队列作为一种关键的数据结构,为线程间安全、高效的数据交换提供了重要支持。Java的java.util.concurrent包中提供了多种阻塞队列的实现,每种实现都有其独特的特点和适用场景。 一、阻塞队列实现类 以下是Java中Blocking…...
Springboot3 + MyBatis-Plus + MySql + Vue + ProTable + TS 实现后台管理商品分类(最新教程附源码)
Springboot3 MyBatis-Plus MySql Uniapp 商品加入购物车功能实现(针对上一篇sku) 1、效果展示2、数据库设计3、后端源码3.1 application.yml 方便 AliOssUtil.java 读取3.2 model 层3.2.1 BaseEntity3.2.1 GoodsType3.2.3 GoodsTypeSonVo3.3 Controll…...
消费电子制造企业如何使用SAP系统提升运营效率与竞争力
在当今这个日新月异的消费电子市场中,企业面临着快速变化的需求、激烈的竞争以及不断攀升的成本压力。为了在这场竞赛中脱颖而出,消费电子制造企业纷纷寻求数字化转型的突破点,其中,SAP系统作为业界领先的企业资源规划(ERP)解决方…...
算法记录——树
二叉树 3.1二叉树的最大深度 思路:二叉树的最大深度 根节点的最大高度。因此本题可以转换为求二叉树的最大高度。 而求高度的时候应该采用后序遍历。遍历顺序为:左右中。每次遍历的节点按后序遍历顺序,先收集左右孩子的最大高度,…...
单片机在控制和自动化任务中的应用场景广泛
单片机在控制和自动化任务中的应用场景广泛,以下是一些具体示例: 1. 家电控制 洗衣机:单片机用于控制洗衣周期、温度和水位。微波炉:控制加热时间、功率和用户界面。 2. 工业自动化 生产线监控:单片机用于控制传送…...
深圳做网站龙华新科/百度关键词查询
一、日常关注的问题1、我们的日志生成速度?1、每天生成多少日志、产生多少redo logmysql> show global status like Innodb_os_log_written;-------------------------------| Variable_name | Value |-------------------------------| Innodb_os_log_written |…...
python做动态网站/加盟培训机构
引用 C中有一个很方便的语法叫做引用,作用就是使得函数能够对传入的参数作出全局有效的改动。用法很简单,就是在传入参数的类型后面加上&就可以指明传入的参数是引用。 例子: #include <stdio.h>void change(int& x){x 1; } i…...
网站关键词优化是什么/快速排名工具免费
本篇文章给大家带来的内容是关于Vue.js路由器的使用方法总结(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。是用于 路由器的无刷新跳转改变 标签默认显示标签标签默认显示 Dom 为 主页通过 tag 属性可以改变 如&…...
网站开发的教学视频教程/百度搜索引擎的特点
第一种就是网上大多数使用的方法,英文的教程,这里不翻译了,非常简单,一看就懂。但发现这种设置给出的字体不全,那如何来让控制台使用UbuntuMono字体呢?(第二种方法。)第一种方法To adjust the font/font-si…...
郴州网红景点排名/广州seo网站营销
网站后台频繁退出严重影响到站长们对后台的使用,很多站长在批量添加商品,对商品进行描述的时候,往往时间是略长的,而这样的操作就会超出ecshop程序默认限制的时间值,这样就会导致弹出。无忧主机php空间后台也有类似的功…...
银川网站建设价格/百度推广关键词和创意
1. 支持手机、pad等移动设备远程控制功能。2、支持DLNA、Airplay、QPaly等协议。3、Cortex-A9四核,7寸电容触摸屏,1024*600高清分辨屏,标配通用的网络接口,内置wifi无线连接。4、功率:35W*45、4声道输出,支…...