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…...
机器学习笔记之最优化理论与方法(四) 凸函数:定义与基本性质
机器学习笔记之最优化理论与方法——再回首:凸函数定义与基本性质 引言凸函数的定义严格凸函数凸函数的推论:凹函数 常见凸函数凸函数的基本性质几种保持函数凸性的运算凸集与凸函数之间的关联关系 引言 本节将介绍凸函数定义及其基本性质。 本文是关于…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
