useTransition:开启React并发模式
写在前面:并发
并发模式(Concurrent Mode)1的一个关键特性是渲染可中断。
React 18 之前,更新内容渲染的方式是通过一个单一的且不可中断的同步事务进行处理。同步渲染意味着,一旦开始渲染就无法中断,直到用户可以在屏幕上看到渲染结果。
在并发渲染中,React 可以开始渲染一个更新,然后中途挂起,稍后又继续;甚至可能完全放弃一个正在进行的渲染。整个过程 UI 会保持一致。为了实现这一点,它会在整个 DOM 树被计算完毕前一直等待,完毕后再执行 DOM 变更。这样做,React 就可以在后台提前准备新的屏幕内容,而不阻塞主线程。这意味着用户输入可以被立即响应,即使存在大量渲染任务,也能有流畅的用户体验。
通过 time slice 将任务拆分为多个,然后 React 根据优先级来完成调度策略,将低优先级的任务先挂起,将高优先级的任务分配到浏览器主线程的一帧的空闲时间中去执行,如果浏览器在当前一帧中还有剩余的空闲时间,那么 React 就会利用空闲时间来执行剩下的低优先级的任务。
React 18 之后,可以立即开始使用并发模式的功能。如,可以使用 useTransition
在屏幕内容之间进行导航,而不会阻塞用户输入;或者使用 useDeferredValue
来节流处理开销巨大的重新渲染。
- useTransition:用于标记状态更新为非阻塞,保持 UI 响应性,适合处理耗时操作导致的状态变化;
- useDeferredValue:主要用于延迟渲染以提升性能和用户体验,特别是在快速变化的输入或数据加载过程中。
useTransition/startTransition
useTransition
用于将某些状态更新标记为非阻塞的 transition,以保持用户界面的响应性,特别是在处理耗时的状态更新时。
const [isPending, startTransition] = useTransition()
过渡(transition)更新是 React 中一个新的概念,用于区分紧急和非紧急的更新。
- 紧急更新 对应直接的交互,如输入,点击,按压等。需要立即响应的行为,如果不立即响应会给人卡顿的感觉。
- 过渡更新 将 UI 从一个视图过渡到另一个。不需要即时响应,有些延迟是可以接受的。
import { startTransition } from 'react';// 紧急更新: 显示输入的内容
setInputValue(input);// 将任何内部的状态更新都标记为过渡更新
startTransition(() => {// 过渡更新: 展示结果setSearchQuery(input);
});
如果一个过渡更新被用户中断(比如,快速输入多个字符),React 将会抛弃未完成的渲染结果,然后仅渲染最新的内容。
通过 transition,UI 仍将在重新渲染过程中保持响应性。
👀 官方示例:
用户点击“Posts”,然后立即点击“Contact”。
🌾 未使用 transition
⚠️ 应用程序在渲染减速选项卡时会冻结,UI 将变得无响应。Posts渲染完后,Contact 才渲染!
🌴 使用 transition
function selectTab(nextTab) {startTransition(() => {setTab(nextTab);});}
⚠️ 这会中断“Posts”的缓慢渲染,而“Contact”选项卡将会立即显示。
👀 经典案例-毕哥达拉斯树2:
const [isLeaning, startLeaning] = useTransition()function changeTreeLean(event) {const value = Number(event.target.value);setTreeLeanInput(value); // update 滑块// 开启 transitionif (enableStartTransition) {startLeaning(() => {setTreeLean(value);});} else {setTreeLean(value);}
}
🌾 全部为紧急更新:
通过下述 gif,可以明显察觉到,滑块到右侧已经卡住了。
🌴头部滑块为紧急更新,树为非紧急更新:
通过下述 gif,可以明显察觉到,滑块一直保持响应,而“树”直接渲染了最终结果。
开启 transition 有两种方式:
useTransition
: 一个用于开启过渡更新的 Hook,组件或自定义 Hook 内部调用。startTransition
: 当 Hook 不能使用时,用于开启过渡的方法。
传递给 Transition
的函数必须是同步的。React 会立即执行此函数,并将在其执行期间发生的所有状态更新标记为 transition。如果在其执行期间,尝试稍后执行状态更新(例如在一个定时器中执行状态更新),这些状态更新不会被标记为 transition。
标记为 transition 的状态更新将被其他状态更新打断。打断的内容被挂起,过渡机制会告诉 React 在后台渲染过渡内容时继续展示当前内容。
只有在可以访问该状态的 set
函数时,才能将其对应的状态更新包装为 transition。如果想启用 transition 以响应某个 prop 或自定义 Hook 值,需要使用 useDeferredValue
。
useDeferredValue
useDeferredValue
用于延迟更新 UI 的某些部分,以便在新内容加载期间显示旧内容,或者在用户输入快速时,避免界面频繁刷新导致的卡顿。
一旦 React 完成原始的重新渲染,它会立即开始使用新的延迟值处理后台重新渲染。由事件(例如输入)引起的任何更新都会中断后台重新渲染,并被优先处理。
const deferredValue = useDeferredValue(value) // value可以是任何类型
⚠️ 向
useDeferredValue
传递原始值(如字符串和数字)或在渲染之外创建的对象。如果在渲染期间创建了一个新对象,并立即将其传递给useDeferredValue
,那么每次渲染时这个对象都会不同(使用Object.is
进行比较),这将导致后台不必要的重新渲染。a1 = {a: 1} a2 = {a: 1} Object.is(a1, a2) // false
useDeferredValue
允许推迟渲染树的非紧急更新。这和防抖操作非常相似,但是有一些改进。它没有固定的延迟时间,React 会在第一次渲染在屏幕上出现后立即尝试延迟渲染。延迟渲染是可中断的,它不会阻塞用户输入。
- 当需要在用户输入时显示过时的数据,以避免界面闪烁或卡顿。
- 与
<Suspense>
集成,可以在数据加载期间显示旧内容而不是后备方案。
示例:
export default () => {const [query, setQuery] = useState('');return (<><label>Search albums:<input value={query} onChange={e => setQuery(e.target.value)} /></label><Suspense fallback={<h2>Loading...</h2>}><SearchResults query={query} /></Suspense></>);
}
尝试输入 "a"
,等待结果出现后,将其编辑为 "ab"
。此时 "a"
的结果会被加载中的后备方案替代。
使用 useDeferredValue
将延迟版本的查询参数向下传递。 延迟 更新结果列表,继续显示之前的结果,直到新的结果准备好。
export default function App() {const deferredQuery = useDeferredValue(query);return (<>{...}<Suspense fallback={<h2>Loading...</h2>}><SearchResults query={deferredQuery} /></Suspense></>);
}
输入 "a"
,等待结果加载完成,然后将输入框编辑为 "ab"
。注意,现在你看到的不是 suspense 后备方案,而是旧的结果列表,直到新的结果加载完成
防抖&节流
- 防抖 是指在用户停止输入一段时间(例如一秒钟)之后再更新列表。
- 节流 是指每隔一段时间(例如最多每秒一次)更新列表。
与防抖或节流, useDeferredValue
有两大优势:
-
不需要选择任何固定延迟时间。如果用户的设备很快(比如性能强劲的笔记本电脑),延迟的重渲染几乎会立即发生并且不会被察觉。如果用户的设备较慢,那么列表会相应地“滞后”于输入,滞后的程度与设备的速度有关。
-
执行的延迟重新渲染默认是可中断的。这意味着,如果 React 正在重新渲染一个大型列表,但用户进行了另一次键盘输入,React 会放弃该重新渲染,先处理键盘输入,然后再次开始在后台渲染。相比之下,防抖和节流仍会产生不顺畅的体验,因为它们是阻塞的:它们仅仅是将渲染阻塞键盘输入的时刻推迟了。
如果要优化的工作不是在渲染期间发生的,那么防抖和节流仍然非常有用。例如,它们可以让你减少网络请求的次数。你也可以同时使用这些技术。而 useDeferredValue
更适合优化渲染,因为它与 React 自身深度集成,并且能够适应用户的设备。
https://zh-hans.react.dev/blog/2022/03/29/react-v18#what-is-concurrent-react 什么是并发 React ↩︎
https://react-fractals-git-react-18-swizec.vercel.app/ react CM startTransition 示例 ↩︎
相关文章:

useTransition:开启React并发模式
写在前面:并发 并发模式(Concurrent Mode)1的一个关键特性是渲染可中断。 React 18 之前,更新内容渲染的方式是通过一个单一的且不可中断的同步事务进行处理。同步渲染意味着,一旦开始渲染就无法中断,直到…...

Android 12系统源码_多窗口模式(二)系统实现分屏的功能原理
前言 上一篇我们具体分析了系统处于多窗口模式下,Android应用和多窗口模式相关方法的调用顺序,对于应用如何适配多窗口模式有了一个初步的认识,本篇文章我们将会结合Android12系统源码,具体来梳理一下系统是如何触发多窗口分屏模…...

字符函数:分类函数与转换函数
字符函数 一.字符分类函数二.字符转换函数 在编程的过程中,我们经常要处理字符和字符串,为了方便操作字符和字符串,C语⾔标准库中提供了一系列库函数,接下来我们就学习⼀下这些函数。 一.字符分类函数 C语言中有⼀系列的函数是专门…...

SpringBoot 集成Mybatis
SpringBoot集成第三方技术,一般都分为导坐标,改配置,写代码三个步骤。 集成Mybatis也类似,新建一个SpringBoot项目。修改:pom.xml文件。 一、导入坐标 <!--druid--> <dependency><groupId>com.al…...

C语言-atoi()库函数的模拟实现
文章目录 前言一、atoi()库函数的介绍及使用1.1 atoi()库函数介绍1.2 atoi()库函数使用 二、atoi()库函数的模拟实现2.1 函数设计2.2 函数实现思路2.3 具体实现2.4 测试 总结 前言 本篇文章介绍c语言中库函数atoi()的使用,以及模拟实现库函数。 一、atoi()库函数的…...

定时监测服务器磁盘是否超过阈值,超过就删除docker 镜像
达到指定百分比 删除镜像脚本 df -h 查找到 内存占用信息 ,得到的 文件系统名称是 overlay的,Use% 达到70就进行删除docker 镜像 #!/bin/bash# 设置磁盘使用阈值 THRESHOLD70# 获取 overlay 文件系统的磁盘使用百分比 DISK_USAGES$(df -h | grep overl…...

UDP聊天室
服务器端 #include <myhead.h>#define SER_IP "192.168.124.38" #define SER_PORT 8888 #define RBUFSIZE 128 #define WBUFSIZE 128typedef struct node{char usrName[20];struct sockaddr_in cli_sockaddr;struct node* next; }node, *node_p;node_p create…...

LLM多模态——GPT-4o改变人机交互的多模式 AI 模型应用
1. 概述 OpenAI 发布了迄今为止最新、最先进的语言模型 – GPT-4o也称为“全“ 模型。这一革命性的人工智能系统代表了一次巨大的飞跃,其能力模糊了人类和人工智能之间的界限。 GPT-4o 的核心在于其原生的多模式特性,使其能够无缝处理和生成文本、音频…...

安卓手机APP开发__蓝牙功能概述
安卓手机APP开发__蓝牙功能概述 目录 概述 基本内容 关键的类和接口 概述 安卓平台支持了蓝牙网络栈,它允许一个设备和其它的蓝牙设备进行无线的交换数据。 APP的框架…...

get和post的区别,二者是幂等的吗?
一、什么是幂等 所谓幂等性通俗的将就是一次请求和多次请求同一个资源产生相同的副作用。 维基百科定义:幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。 在编程中一个幂等操作的特点是其任意多次执…...

农场--Kruskal应用--c++
【题目要求】 农场里有一些奶牛,作为食物的草料不够了。农场主需要去别的农场借草料。该地区有N (2 < N < 2,000) 个农场,农场名称用数字N标识,农场之间的道路是双向的,一共有M (1 < M < 10,000)条道路,单…...

【Crypto】Rabbit
文章目录 一、Rabbit解题感悟 一、Rabbit 题目提示很明显是Rabbit加密,直接解 小小flag,拿下! 解题感悟 提示的太明显了...

IRFB3207PBF TO-220 N沟道75V/180A 直插MOSFET场效应管
英飞凌(Infineon)的 IRFB3207PBF 是一款高性能的 N 沟道 MOSFET,适用于多种电子设备和系统中的高侧开关应用。以下是 IRFB3207PBF 的一些典型应用场景: 1. 电源管理:在电源管理系统中,IRFB3207PBF 可以作为…...

基于单张图片快速生成Metahuman数字人(模型贴图绑定)的工作流演示
基于单张图片快速生成Metahuman数字人(模型贴图绑定)的工作流演示 MetahumanModeler, 是我基于facebuilder以及metahuman的理解开发而成,插件可以基于单张图片生成metahuman拓扑结构的面部3d模型,同时生成对应的面部的贴图&#…...

MySQL数据库下的Explain命令深度解析
Explain是一个非常有的命令,可以用来获取关于查询执行计划的信息,以及如何解释输出。Explain命令是查看查询优化器如何决定执行查询的主要方法。这个功能有一定的局限性,并不总是会说出真相,但是它的输出是可以获取的最好信息&…...

防火墙技术基础篇:基于IP地址的转发策略
防火墙技术基础篇:基于IP地址的转发策略的应用场景及实现 什么是基于IP地址的转发策略? 基于IP地址的转发策略是一种网络管理方法,它允许根据目标IP地址来选择数据包的转发路径。这种策略比传统的基于目的地地址的路由更灵活,因…...

OpenFeign快速入门 替代RestTemplate
1.引入依赖 <!--openFeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--负载均衡器--><dependency><groupId>org.spr…...

自动化测试--利用pytest实现整条业务链路测试
概述 前面一章讲解了单个接口的测试,但是实际项目中,因为权限和登录状态的限制,大部分接口没办法直接访问到,这时候我们想访问到一个系统的接口,就需要模拟用户登录拿到用户的token和所拥有的权限之后再将这些信息…...

学习其他推理判断
学习其他推理判断 1.类比推理1.1语义关系1.2逻辑关系1.3 语法关系2.定义判断3.翻译推理3.1前推后:A→B3.2后推前:B→A3.3推理规则4.组合排列5.日常结论6.逻辑论证6.1削弱题型6.2加强题型7.原因解释1.类比推理 类比推理:给出一组相关的词,通过观察分析,在备选答案中找出一组…...

Centos7环境下MySQL5.7.38 安装开源审计插件 mysql-audit
MySQL安装开源审计插件 mysql-audit MySQL 5.7.38安装审计插件 mysql-audit安装MySQL1.查看Linux服务器版本和glibc版本2.根据自己的系统下载对应的MySQL版本,由于mysql-audit并不支持所有版本的MySQL,所以在确定MySQL版本之前请注意下插件支持的MySQL版…...

基于深度学习的表情识别系统
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 随着人工智能技术的快速发展,表情识别成为了人机交互领域的一个研究热点。表情识别技术旨…...

Debug-010-git stash的用法及使用场景
问题原因: 其实也不是最近,就是之前就碰到过这个问题,那就是我正在新分支开发新功能,开发程度还没有到可以commit的程度,我不想提交(因为有些功能没有完全实现,而且没有自测的话很容易有问题,提…...

RustGUI学习(iced/iced_aw)之扩展小部件(二十五):如何使用tab部件来创建tab多页面切换?
前言 本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1. 概述 这是本专栏的第二十五篇,主要讲述tab页面切换部件的使用,会结…...

P2P服务端模型配合 Tool.net P2pServerAsync 类使用
Tool.Net 支持的 P2P 服务器模型实例 说明服务器部分相关代码相关调用实例Tcp版本Udp版本 最后附一张思维图 说明 当前文章,仅是Tool.Net 开源库的一个缩影。本次更新V5.0版本以上提供支持。可以提供简单实现P2P功能用于业务开发。 服务器部分相关代码 完整代码&…...

Python语法学习之 - 生成器表达式(Generator Expression)
第一次见这样的语法 本人之前一直是Java工程师,最近接触了一个Python项目,第一次看到如下的代码: i sum(letter in target_arr for letter in source_arr)这条语句是计算source 与 target 数组中有几个单词是相同的。 当我第一眼看到这样…...

docker所在磁盘空间不足 迁移数据
1.查看原始目录docker info | grep "Docker Root Dir" 一般在/var/lib/docker 2.停止docker service docekr stop 3.移动数据 注意 移动前不要创建docker目录! mv /var/lib/docker /home/docker 4.进入目录查看是否与原始目录相同,确认一…...

15、24年--信息系统管理——管理要点
1、数据管理 数据管理使指通过规划、控制与提供数据和信息资产的职能,包括开发、执行和监督有关数据的计划、策略、方案、项目、流程、方法和程序,以获取、控制、保护、交付和提高数据和信息资产价值。 DCMM定义了数据战略、数据治理、数据架构、数据应用、数据安全、…...

如何使用 CapSolver 扩展找到 Google reCAPTCHA 站点密钥?
网站安全性在当今至关重要,Google reCAPTCHA 作为防止垃圾邮件和滥用行为的前线防御系统起着关键作用。reCAPTCHA 站点密钥是确保网站交互由人类驱动的唯一标识符。了解如何找到这个密钥对于网站管理员和开发人员来说至关重要。 什么是 reCAPTCHA 站点密钥 reCAPT…...

安卓分身大师4.6.0解锁会员安卓14可用机型伪装双开多开
需登录解锁会员功能,除了加速进入不能, 其他主要功能都是可以使用,由于验证较多一些功能需要特定操作使用,进行伪装时请不要直接伪装,先生成成功后再进行自定义伪装!链接:https://pan.baidu.com…...

攻防世界-mobile-easy-app详解
序言 这道题网上很多分析,但是分析的都是arm版本的,我选了arm64的来分析,arm64相比arm难度高一些,因为arm64编译器搞了inline优化,看起来略抽象 分析 这道题逻辑很简单,输入flag然后一个check函数验证&a…...