React Hooks总览
总览
hooks 功能分类 | 具体 hooks | 具体功能 | React v18新特性 | 跨端支持 |
---|---|---|---|---|
数据更新驱动 | useState | 定义要在页面中渲染的数据 | ❌ | ✔ |
useReducer | 定义要在页面中渲染的数据,且这个数据有多种处理逻辑 | ❌ | ✔ | |
useSyncExternalStore | concurrent 模式下,订阅外部 store 的行为,触发更新 | ✔ | ❌ | |
useTransition | concurrent 模式下,在不阻塞 UI 的情况下来更新状态 | ✔ | ❌ | |
useDeferredValue | concurrent 模式下,延迟更新 UI 的某些部分 | ✔ | ❌ | |
执行副作用 | useEffect | 异步状态下,视图更新后,执行副作用 | ❌ | ✔ |
useLayoutEffect | 同步状态下,视图更新前,执行副作用 | ❌ | ✔ | |
useInsertionEffect | 用于处理 CSS-in-JS 缺陷问题 | ✔ | ❌ | |
状态获取与传递 | useContext | 接收祖先组件的 context 传递的信息 | ❌ | ✔ |
useRef | 存储一个不需要渲染的值 | ❌ | ✔ | |
useImperativeHandle | 配合 forwardRef 将子组件的 ref 传递给父组件 | ❌ | ✔ | |
状态派生与保存 | useMemo | 缓存结果 | ❌ | ✔ |
useCallback | 缓存函数 | ❌ | ✔ | |
工具 hooks | useId | 生成唯一的 ID | ✔ | ❌ |
useDebugValue | 在 React 开发者工具中为自定义 Hook 添加标签 | ❌ | ❌ |
数据更新驱动
useState
useState 允许向组件添加一个 状态变量。
/*** @param { any } initValue:初始值* @return { array } arr:状态信息state { any } 状态名setState { function } 修改状态的函数*/
const [state, setState] = useState(initValue)// 第一种方式:传入值
setState(newValue);// 第二种方式:传入函数
setState(preValue => newValue);
示例:
const [number, setNumber] = useState(0)// 第一种方式:传入值
setNumber(number + 1)// 第二种方式:传入函数
setNumber(number => number + 1)
注意事项:
- 在函数组件一次执行上下文中,state 的值是固定不变的
- 如果两次 setState 传入相同的 state 值,那么组件就不会更新
- 当触发 setState 在当前执行上下文中获取不到最新的 state,只有在下一次组件 render 中才能获取到
useReducer
useReducer 能够在无状态组件中运行的类似 redux 的功能 api 。
当对一个状态有多种处理逻辑时建议使用 useReducer。
/*** @param { function } reducer:处理函数* @param { any } initValue:初始值* @param { function } compareInitValueFn:计算初始值的函数,如果存在则初始值为 compareInitValueFn(initValue)* @return { array } arr:状态信息state { any } 状态名dispatchState { function } 派发状态的函数*/
const [state, dispatchState] = useReducer(stateReducer, initValue, compareInitValueFn?)
示例:
const numberReducer = (state, action) => {switch(action.type) {case 'add':return state + 1;case 'reduce':return state - 1;}
}
const [number, dispatchNumber] = useReducer(numberReducer, 0);dispatchNumber({type: 'add'
})
useSyncExternalStore
useSyncExternalStore 可以订阅外部 store。
/*** @param { function } subscribe:订阅函数* @param { function } getSnapshot:返回组件需要的 store 中的数据快照 带有记忆功能的选择器* @param { function } getServerSnapshot:用于 hydration 模式下的 getSnapshot* @return { any } snapshot:该 store 的当前快照*/
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?)
示例:
import { combineReducers , createStore } from 'redux'/* number Reducer */
function numberReducer(state = 1, action) {switch(action.type) {case 'ADD':return state + 1case 'DEL':return state - 1default:return state}
}/* 注册reducer */
const rootReducer = combineReducers({ number: numberReducer })
/* 创建 store */
const store = createStore(rootReducer, { number: 1})function Index(){/* 订阅外部数据源 */const state = useSyncExternalStore(store.subscribe, () => store.getState().number)return (<div><button onClick={()=>store.dispatch({type:'ADD'})}>{ state }</button></div>)
}
注意:
getSnapshot 返回的 store 快照必须是不可变
如果底层 store 有可变数据,要在数据改变时返回一个新的不可变快照;否则,返回上次缓存的快照。
如果在重新渲染时传入一个不同的 subscribe 函数,React 会用新传入的 subscribe 函数重新订阅该 store
可以通过在组件外声明 subscribe 来避免。
useTransition
useTransition 可以在不阻塞 UI 的情况下来更新状态。
/*** @return { array } transitionInfo:转换状态信息isPending { boolean } 是否存在待处理的转换startTransition { function } 将状态由更新状态标记为转换状态@param { function } scope:作用域函数*/
const [isPending, startTransition] = useTransition()
示例:
export default function Index(){const [number, setNumber] = React.useState(0) // 需要立即响应的任务,立即更新任务const [count, setCount] = useState(0) // 不需要立即响应的任务,过渡任务const [isPending, startTransition] = useTransition() const btnClick = () => {setNumber(number + 1) // 立即更新startTransition(() => { // startTransition 里面的任务优先级低setCount(count + 1);})}return (<div><button onClick={()=>btnClick()}>{ count }</button></div>)
}
注意:
只有在可以访问该状态的
set
函数时,才能将更新包装为转换状态如果想响应某个 prop 或自定义 Hook 值启动转换,请尝试使用 useDeferredValue
传递给 startTransition 的函数必须是同步的。
useDeferredValue
useDeferredValue 可以延迟更新 UI 的某些部分。
/*** @param { any } value:延迟更新的值* @return { any } deferredValue:延迟更新的值*/
const deferredValue = useDeferredValue(value)
示例:
export default function Index(){const [number, setNumber] = useState(1) // 需要立即响应的任务,立即更新任务const deferNumber = useDeferredValue(number) // 把状态延时更新,类似于过渡任务const btnClick = () => {setNumber(number + 1) // 立即更新}return (<div><button onClick={()=>btnClick()} >{ deferNumber }</button></div>)
}
- 在组件的初始渲染期间,返回的延迟值将与提供的值相同
- 但是在组件更新时,React 将会先尝试使用旧值进行重新渲染(因此将返回旧值)
- 然后再在后台使用新值进行另一个重新渲染(这时将返回更新后的值)
注意:应该向 useDeferredValue 传递原始值或在渲染之外创建的对象。
如果在渲染期间创建了一个新对象,并立即将其传递给 useDeferredValue,那么每次渲染时这个对象都会不同,这将导致后台不必要的重新渲染。
执行副作用
useEffect
useEffect 用于异步监听组件的 state 属性,在浏览器绘制后执行。
/*** @param { function } setup:回调函数,初始化执行一次,当监听的 state 改变时执行,返回一个当组件被销毁时执行的函数* @param { array } dependencies:要监听的 state,默认为所有 state,空数组表示不监听任何 state*/
useEffect(setup, dependencies?)
示例:
useEffect(() => {let timer = setInterval(() => {console.log(1)}, 1000)return () => {timer = null}
}, [])
可以把 useEffect 看作是以下三个生命周期的组合:
- componentDidMount():组件挂载完成执行 callback
- componentDidUpdate():监听的 state 变化执行 callback
- componentWillUnmount():组件将要销毁执行 callback 的返回函数
useLayoutEffect
useLayoutEffect 是 useEffect 的同步版本,并且是在浏览器绘制前执行,主要用于操作 DOM。
注意:useLayoutEffect callback 中代码执行会阻塞浏览器绘制
/*** @param { function } setup:回调函数,初始化执行一次,当监听的 state 改变时执行,返回一个当组件被销毁时执行的函数* @param { array } dependencies:要监听的 state,默认为所有 state,空数组表示不监听任何 state*/
useLayoutEffect(setup, dependencies?)
useInsertionEffect
useInsertionEffect 可以在布局副作用触发之前将元素插入到 DOM 中。
注意:useInsertionEffect 是为 CSS-in-JS 库的作者特意打造的。除非正在使用 CSS-in-JS 库并且需要注入样式,否则应该使用 useEffect 或者 useLayoutEffect。
/*** @param { function } setup:回调函数,初始化执行一次,当监听的 state 改变时执行,返回一个当组件被销毁时执行的函数* @param { array } dependencies:要监听的 state,默认为所有 state,空数组表示不监听任何 state*/
useInsertionEffect(setup, dependencies?)
状态获取与传递
useContext
useContext 用于接收祖先组件的 context 传递的信息。
/*** @param { context } context:context 容器* @return { any } value:祖先组件传递的 context*/
const value = useContext(context)
示例:
// 1、创建 context 容器
const NumberContext = createContext(null);// 2、祖先组件定义 Provider
function GrandFather() {return (<NumberContext.Provider value={1}><Father /></NumberContext.Provider>);
}// 3、父组件中使用子组件
function Father() {return (<Son></Son>)
}// 4、子组件中通过 useContext 接收祖先组件传递的数据
function Son() {const number = useContext(NumberContext);
}
useContext()
总是在调用它的组件 上面 寻找最近的 provider。它向上搜索,不考虑 调用useContext()
的组件中的 provider。
useRef
useRef 可以存储一个不需要渲染的值。
与 state 的区别:ref 的改变不会渲染,state 会
与普通对象的区别:ref 的值不会重置,普通对象会
/*** @param { any } initValue:初始值* @return { ref } ref:只有 current 属性的 ref 对象*/
const ref = useRef(initValue)
示例:
function Demo() {const divRef = useRef(null)return (<div ref={divRef}>ref节点</div>)
}
不要在 渲染期间 写入或者读取
ref.current
。可以在 事件处理程序或者 effects 中读取和写入 ref。
useImperativeHandle
useImperativeHandle 配合 forwardRef 将子组件的 ref 传递给父组件。
/*** @param { ref } ref:forWardRef 渲染函数中获得的第二个参数* @param { function } createHandle:处理函数,返回值作为暴露给父组件的 ref 对象* @param { array } dependencies:依赖项*/
useImperativeHandle(ref, createHandle, dependencies?)
示例:
// 子组件
const Son = forwardRef((props, ref) => {const divRef = useRef(null)useImperativeHandle(ref, () => {return {sendData: () => {console.log(divRef.current)}}}, [])return <div ref={divRef}>子组件</div>
})
// 父组件
function Parent() {const sonRef = useRef(null)return <Son ref={sonRef}></Son>
}
状态派生与保存
useMemo
useMemo 在每次重新渲染的时候能够缓存计算的结果。
/*** @param { function } calculateValue:要缓存计算值的函数,返回值作为缓存值* @param { array } dependencies:依赖项数组* @return { any } cachedValue:缓存值(calculateValue 返回的值)*/
const cachedValue = useMemo(calculateValue, dependencies)
- cachedValue 初次为不带参数调用 calculateValue 的返回值
- 后续如果依赖项没有变,就返回上次缓存的值;否则将再次调用 calculateValue,并返回最新结果
注意:应该仅仅把 useMemo 作为性能优化的手段
useCallback
useCallback 允许在多次渲染中缓存函数。
/*** @param { function } fn:想要缓存的函数* @param { array } dependencies:依赖项数组* @return { function } cachedFn:缓存的函数*/
const cachedFn = useCallback(fn, dependencies)
- 在初次渲染时,useCallback 返回你已经传入的 fn 函数
- 在之后的渲染中, 如果依赖没有改变,useCallback 返回上一次渲染中缓存的 fn 函数;否则返回这一次渲染传入的 fn。
注意:
- 不应在循环或者条件语句中调用 useCallback
- 应该仅仅把 useMemo 作为性能优化的手段
工具 hooks
useId
useId 可以生成传递给无障碍属性的唯一 ID。
/*** @return { string } id:唯一的字符串 ID*/
const id = useId()
注意:不要使用 useId 来生成列表中的 key。
useDebugValue
useDebugValue 可以在 React 开发工具 中为自定义 Hook 添加标签。
/*** @param { any } value:在 React 开发工具中显示的值* @param { function } format:如果传入,则值为将 value 作为参数调用 format 返回的值;否则值为 value*/
useDebugValue(value, format?)
相关文章:

React Hooks总览
总览 hooks 功能分类具体 hooks具体功能React v18新特性跨端支持数据更新驱动useState定义要在页面中渲染的数据❌✔useReducer定义要在页面中渲染的数据,且这个数据有多种处理逻辑❌✔useSyncExternalStoreconcurrent 模式下,订阅外部 store 的行为&am…...

风向变了!智能汽车何以「降本」
随着软件定义汽车的概念逐步落地,以及底盘、动力、座舱、智驾、车身等不同域(分布式或者混合式)的功能更新迭代和融合,汽车行业正在意识到:底层硬件架构重构的迫切性。 事实上,早在2016年,作为传…...

后端面试话术集锦第 十五 篇:java线程面试话术
这是后端面试集锦第十五篇博文——java线程面试话术❗❗❗ 1. 创建线程的方式 首先呢,Thread类本质上是实现了Runnable接口,代表一个线程的实例。 所以,我们可以编写一个类,继承Thread类,或者直接实现Runnable接口。然后,再重写下~run方法就行了。启动线程的方式就是调…...

cocos creator配置终端调试
在launch.json里添加"preLaunchTask":“CocosCreator compile” 在cocos creator里选择开发者,visual studio code工作流,选择添加编译任务。 添加 settings.json {"files.exclude":{"**/.git": true,"**/.DS_Sto…...

达梦类型转换问题-float转换为varchar
表结构 CREATE TABLE "SYSDBA"."TABLE_2" ( "COLUMN_1" FLOAT, "COLUMN_2" NUMERIC(22,6)) STORAGE(ON "MAIN", CLUSTERBTR) ; 表数据: 查询,将numeric转换为float,再转换为varchar&…...

怎么用postman连接websocket
点击右侧栏的Collections,然后点击旁边的New,然后点击其中的WebSocket Request,然后输入Url,点击Connection,这里需要注意的是Url不能加上http://,因为这个不是http协议。...

需求分析入门
认识管理软件 什么是管理软件 管理软件就是用来辅助企业进行管理的软件,既包括对企业“人、财、物”相关的资产信息的管理,也包括对企业“供、产、销”相关的业务活动信息的管理。管理软件的重点在于管理信息的收集、流转,资源的共享、集成…...

攻防世界-php_rce
原题 解题思路 thinkPHP.0有漏洞,ThinkPHP5.x rec 漏洞分析与复现。本题就是利用漏洞查找。格式是: ?sindex/\think\app/invokefunction&functioncall_user_func_array&vars[0]system&vars[1][]命令。 ls查看文件没什么东西,r…...

最小生成树Kruskal、Prim算法C++
什么是最小生成树 连通图: 在无向图中,若从顶点v1到顶点v2有路径,则称顶点v1和顶点v2是连通的。如果图中任意一对顶点都是连通的,则称此图为连通图。 生成树: 一个连通图的最小连通子图称作为图的生成树。有n个顶点的…...

系统架构设计师-计算机系统基础知识(2)
目录 一、存储管理 1、页式存储 2、段式存储 3、段页式存储 二、磁盘管理 1、先来先服务FCFS 2、最短寻道时间优先SSTF 三、文件系统 1、文件基本概念 2、文件的类型: 3、索引文件结构 4、位示图 四、性能指标 五、性能设计 1、阿姆达尔定律 六、性能评估 1、…...

二叉树的介绍
写在前面: 二叉树是数据结构课程中非常重要的内容,我们针对二叉树的概念、性质以及类型展开详细介绍。 一、概念 二叉树(Binary Tree)是n(n>0)个结点的有限集合,该集合或者空集࿰…...

数据结构与算法复杂度介绍
目录 一、基本概念 二、时间复杂度 【2.1】时间复杂度概念 【2.2】大O的渐进表示法 【2.3】举例时间复杂度计算 三、空间复杂度 一、基本概念 数据结构:相互之间存在一种或者多种特定关系的数据元素的集合。在逻辑上可以分为线性结构,散列结构、树…...

CentOS 安装蒲公英
官方教程链接: https://service.oray.com/question/5063.html 教程使用的是2.3版本,官网下载的最新版是2.4,所以命令会有所不同 安装成功后, 任意路径下执行pgyvisitor,调出交互界面pgyvisitor login,登录…...

英语语法基础--思维导图
思维导图通常用于可视化和整理信息,而英文语法非常广泛且复杂,无法在一个简单的思维导图中完整表示。然而,我可以提供一个简化版本的英文语法思维导图,列出一些主要的语法概念和部分示例。 请注意,这只是一个基本的概…...

Android泛型详解
参考文献:https://pingfangx.github.io/java-tutorials/java/generics/types.html 1,什么是泛型? Java泛型(generics)是JDK5中引入的一个新特性,泛型提供了 编译时类型安全检测机制, 该机制允许程序员在编译时检测到…...

C++信息学奥赛1178:成绩排序
#include<bits/stdc.h> using namespace std; int main(){int n;cin>>n; // 输入整数 n,表示数组的大小int arr[n]; // 创建大小为 n 的整型数组 arrstring brr[n]; // 创建大小为 n 的字符串数组 brrfor(int i0;i<n;i) cin>>brr[i]>>ar…...

【计算机视觉 | 目标检测】目标检测常用数据集及其介绍(七)
文章目录 一、Cops-Ref二、FAT (Falling Things)三、GEN1 Detection (Prophesee GEN1 Automotive Detection Dataset)四、RIT-18五、AGAR (Annotated Germs for Automated Recognition)六、EuroCity Persons七、Freiburg Groceries八、Lytro Illum九、PFN-PIC (PFN Picking Ins…...

100天精通Golang(基础入门篇)——第20天:Golang 接口 深度解析☞从基础到高级
🌷🍁 博主猫头虎🐅🐾 带您进入 Golang 语言的新世界✨✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文并茂…...

ESXi 6.7添加螃蟹2.5g网卡支持
安装了ESXi 6.7,结果机器两块网卡只能识别一块,然后想着不能让另一块浪费啊,开始折腾,看着网上都是找的驱动然后封装进iso,可是我已经装完了,怎么办,然后找到了下面解决方法 1.找驱动 下载RTL81…...

机器学习笔记之最优化理论与方法(四) 凸函数:定义与基本性质
机器学习笔记之最优化理论与方法——再回首:凸函数定义与基本性质 引言凸函数的定义严格凸函数凸函数的推论:凹函数 常见凸函数凸函数的基本性质几种保持函数凸性的运算凸集与凸函数之间的关联关系 引言 本节将介绍凸函数定义及其基本性质。 本文是关于…...

【Git】git tag 查看版本号 | 删除本地 | 删除远程仓库| 批量删除
一、删除指定tag 使用场景:比如我们在本地git tag了一个错误的版本号,但是还没有push,想直接删掉避免污染远程仓库 1、删除指令 要删除指定的Git标签(版本号),您可以使用以下命令: git tag -d 标…...

thinkphp:数据库查询,嵌套别的表的查询(别的表做子查询)
例子 从 vendors 表中选择记录。在 vendors 表中,筛选出具有满足以下条件的 vendor_code 值: 对应的采购订单(在 po_headers_all 表中)存在未完全接收的采购行(在 po_lines_all 表中)。相应的采购订单状态…...

《Linux 系统命令及Shell脚本实践指南》
Linux 系统命令及Shell脚本实践指南 《Linux 系统命令及Shell脚本实践指南》该书从结构上分为三部分:第一部分1.1Linux的历史发展1.2用户管理1.3任务管理单一时刻执行一次任务使用at周期性任务使用:cron表达式,命令crontab 1.4文件管理1.4.1 Linux shell…...

代码随想录算法训练营第三十八天 | ● 理论基础 ● 509. 斐波那契数 ● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯
题目链接:509. 斐波那契数 代码随想录 视频:手把手带你入门动态规划 | LeetCode:509.斐波那契数_哔哩哔哩_bilibili 看完代码随想录之后的想法: 我们要知道动态规划的五部曲; 1,确定dp数组的含义&#x…...

Java分别用BIO、NIO实现简单的客户端服务器通信
分别用BIO、NIO实现客户端服务器通信 BIONIONIO演示(无Selector)NIO演示(Selector) 前言: Java I/O模型发展以及Netty网络模型的设计思想 BIO Java BIO是Java平台上的BIO(Blocking I/O)模型&a…...

React Portals
什么是React Portals React Portals(React 门户)是 React 提供的一种机制,用于将组件渲染到 DOM 树中的不同位置,而不受组件层次结构的限制。它允许你将一个组件的渲染内容“传送”到 DOM 结构中的任何位置,通常用于处…...

Python基础之高级函数
异常捕获 Python中,使用trycatch两个关键字来实现对异常的处理。在我们平时的工作中,异常的出现是在所难免的,但是异常一旦出现,极有可能会直接导致程序崩溃,无法正常运行,所以异常一定要及时的做出对应的…...

CSS3常用的新功能总结
CSS3常用的新功能包括圆角、阴渐变、2D变换、3D旋转、动画、viewpor和媒体查询。 圆角、阴影 border-redius 对一个元素实现圆角效果,是通过border-redius完成的。属性为两种方式: 一个属性值,表示设置所有四个角的半径为相同值ÿ…...

Lvs+KeepAlived高可用高性能负载均衡
目录 1.环境介绍 2.配置keepalived 3.测试 1.测试负载均衡 2.测试RS高可用 3.测试LVS高可用 3.1测试lvs主服务宕机 3.2.测试lvs主服务器恢复 4.我在实验中遇到的错误 1.环境介绍 环境:centos7 RS1---RIP1:192.168.163.145 VIP 192.168.163.200 RS2---RIP2…...

无涯教程-Android Online Test函数
Android在线测试模拟了真正的在线认证考试。您将看到基于 Android概念的多项选择题(MCQ),将为您提供四个options。您将为该问题选择最合适的答案,然后继续进行下一个问题,而不会浪费时间。完成完整的考试后,您将获得在线考试分数。 总问题数-20 最长时间-20分钟 Start Test …...