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…...

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

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...

算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...