React 18 中的并发性

并发性是我们在 React 18 发布后获得的重大成就之一。由于此功能是完全选择加入的,并且 React 18 向后兼容以前的版本,因此您甚至可能没有注意到新功能。那么并发性是什么、它是如何工作的以及它如何改进您的应用程序的呢?

什么是并发

并发是一种执行模型,其中程序的不同部分可以无序执行,而不会影响最终结果。您可能听说过不同风格的并发性多线程或多处理。由于浏览器中的 JavaScript 只能访问一个线程(worker 在单独的线程中运行,但它们与 React 并不真正相关),因此我们不能使用多线程来并行我们的一些计算。为了确保资源的最佳使用和页面的响应能力,JS 必须采用不同的并发模型:协作式多任务处理。这听起来可能过于复杂,但不要害怕,您已经熟悉这个模型并且肯定已经使用过它。

我说的是 -s 和 /。协作式多任务处理意味着程序的编写方式使某些部分在等待某些事件时可能会暂停,并在稍后恢复。例如,要等待对 you use 的响应。这告诉浏览器,它可以在响应不存在时暂停当前函数并执行一些其他工作。当响应到达时,浏览器将等待活动函数产生 (using ),然后恢复我们之前的函数,该函数现在可以处理 HTTP 响应。

+ Promise async await fetch await await

它与 React 的关系

在 React 18 之前,React 中的所有更新都是同步的。如果 React 开始处理更新,它无论如何都会完成它(当然,除非你关闭选项卡)。即使这意味着忽略此时发生的用户事件,或者如果您有特别重的组件,则冻结页面。对于较小的更新来说,这很好,但对于涉及渲染大量组件(如路由更改)的更新,它会对用户体验产生负面影响。

React 18 引入了两种类型的更新:紧急状态更新和过渡状态更新。默认情况下,所有状态更新都是紧急的,此类更新不能中断。转换是低优先级更新,可能会被中断。从现在开始,我还将使用“高优先级更新”和“低优先级更新”。

为了保持向后兼容性,默认情况下,React 18 的行为与以前的版本相同,所有更新都是高优先级的,因此是不可中断的。要选择并发呈现,您需要使用 或 将更新标记为低优先级。

+ startTransition 
+ useDeferredValue

中断和切换的工作原理

在渲染低优先级更新时,在渲染每个组件后,React 将暂停并检查是否有高优先级更新需要处理。如果有,React 将暂停当前渲染并切换到渲染高优先级更新。处理完后,React 将返回渲染低优先级更新(如果不再相关,则丢弃它)。除了高优先级更新外,React 还会检查当前渲染是否不需要太多时间。如果是这样,React 将返回给浏览器,因此它可以重新绘制屏幕以避免滞后和冻结。

由于 React 只能在渲染组件之间产生(它不能在组件中间停止),因此如果您有一两个繁重的组件,并发渲染将无济于事。如果组件渲染耗时 300 毫秒,则浏览器将被阻塞 300 毫秒。并发渲染真正闪耀的地方是,当您的组件只是稍微慢一点,但组件的数量如此之多,以至于它们加起来的总渲染时间相当长。

悬念呢?

您可能听说过 CPU 密集型程序。大多数情况下,此类程序会主动使用 CPU 来完成其工作。我们前面提到的慢速组件可以归类为受 CPU 限制的组件:为了更快地渲染,它们需要更多的资源。

与受 CPU 限制的程序相反,有受 IO 限制的程序。此类程序将大部分时间花在与输入输出设备(例如磁盘或网络)交互上。React 中负责处理 IO(主要以网络请求的形式出现)的组件是 Suspense。我介绍了它是如何工作的本指南,您可能想查看一下以更好地了解我们在说什么。

如果组件在低优先级更新期间挂起,则 Suspense 的行为略有不同。如果 Suspense 边界内已经有内容显示,React 不会像往常一样处理暂停并显示回退,而是会暂停渲染并切换到其他任务,直到 promise 解决,然后提交一个包含新内容的完整子树。这样,React 就可以避免隐藏已经存在的内容。如果组件在第一次渲染期间挂起,则会显示回退。

如何启动过渡

有几种方法可以启动转换,其中最基本的是功能。你像这样使用它:

+ startTransition
import { startTransition, useState } from 'react';const StartTransitionUsage = () => {const onInputChange = (value: string) => {setInputValue(value);startTransition(() => {setSearchQuery(value);});};const [inputValue, setInputValue] = useState('');const [searchQuery, setSearchQuery] = useState('');return (<div><SectionHeader title="Movies" /><inputplaceholder="Search"value={inputValue}onChange={(e) => onInputChange(e.target.value)}/><MoviesCatalog searchQuery={searchQuery} /></div>);
};

这里发生的事情是,当用户输入搜索输入时,我们像往常一样更新状态变量,然后调用我们传递一个函数的位置,并进行另一个状态更新。这个函数会立即被调用,React 会记录在执行过程中所做的任何状态更改,并将它们标记为低优先级更新。请注意,只应将同步函数传递给(至少从 React 18.2 开始)。

+ inputValue 
+ startTransition

因此,在我们的示例中,我们实际上启动了两个更新:一个紧急(更新)和一个过渡(更新)。 组件可能会使用 Suspense 通过搜索查询获取电影,这将使该组件受 IO 限制。此外,它可以渲染相当长的电影卡列表,这可能也会使其受 CPU 限制。通过过渡,此组件不会在加载数据时触发悬念回退(将显示过时的 UI),也不会在渲染一长串卡片时冻结我们的浏览器。

+ inputValue 
+ searchQuery 
+ MoviesCatalog

需要注意的是,对于受 CPU 限制的组件,它们应该用 包装,否则它们将在每次高优先级渲染时重新渲染,即使它们的道具没有改变,这将对应用程序的性能造成影响。

+ React.memo

startTransition是最基本的功能,旨在在 React 组件之外使用。为了从 React 组件开始过渡,我们有一个更酷的版本:钩子。

+ useTransition
import { useTransition, useState } from 'react';const UseTransitionUsage = () => {const onInputChange = (value: string) => {setInputValue(value);startTransition(() => {setSearchQuery(value);});};const [inputValue, setInputValue] = useState('');const [searchQuery, setSearchQuery] = useState('');const [isPending, startTransition] = useTransition();return (<div><SectionHeader title="Movies" isLoading={isPending} /><inputplaceholder="Search"value={inputValue}onChange={(e) => onInputChange(e.target.value)}/><MoviesCatalog searchQuery={searchQuery} /></div>)
};

使用此钩子,您不会直接导入;相反,您可以调用钩子,它返回一个包含两个元素的数组:一个布尔值,指示是否有任何低优先级更新正在进行中(从此组件启动)和用于启动转换的函数。

+ startTransition 
+ useTransition() 
+ startTransition

当你以这种方式启动过渡时,React 实际上会做 2 次渲染:一个是高优先级渲染,另一个是低优先级更新,其中包含您传递给的实际状态更改。因此,请谨慎使用。

+ isPendingtrue
+ startTransition
+ React.memo

我们得到的另一个新钩子是,如果在关键组件和重型组件中使用相同的状态,则它非常有用。就像我们上面的例子一样。多么方便,是吧?这是你使用它的方式:

+ useDeferredValue
import { useDeferredValue, useState } from 'react';const UseDeferredValueUsage = () => {const [inputValue, setInputValue] = useState('');const searchQuery = useDeferredValue(inputValue);return (<div><SectionHeader title="Movies" isLoading={inputValue !== searchQuery} /><inputplaceholder="Search"value={inputValue}onChange={(e) => setInputValue(e.target.value)}/><MoviesCatalog searchQuery={searchQuery} /></div>);
};

在低优先级渲染和第一次高优先级渲染中,将存储传递的值并立即返回它,因此他们将是相同的字符串。但是在后续的高优先级渲染中,React 将始终返回存储的值。但它也会将你传递的值与存储的值进行比较,如果它们不同,React 将安排一个低优先级的更新。如果该值在高优先级更新期间再次更改,而低优先级更新正在进行中,React 将丢弃它并使用最新值安排新的低优先级更新。

+ useDeferredValue
+ inputValue
+ searchQuery

使用此钩子,您可以拥有相同状态的两个版本:一个用于输入字段等关键组件(滞后通常是不可接受的),另一个用于搜索结果等组件(用户习惯于较长的延迟)。

结束语

并发肯定是一个有趣的功能,我相信一些复杂的应用程序会从中受益。更重要的是,它可能已经在你最喜欢的 React 框架的后台使用(Remix 和 Next 都使用它进行路由)。而且我怀疑,一旦 Suspense for Data Fetching 达到生产就绪状态,它将更加受欢迎。但就目前而言,您仍有时间学习并逐渐将其应用到您的应用程序中。如果你想深入了解 React 中的并发性,了解更多的细节和历史背景,请查看 Ivan Akulov 的这个演讲,这很好。

公众号:程序员白特

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/624808.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

360度评估的应用场景和评估内容

360度评估是一种多元化的评估工具&#xff0c;它从多个角度获取对个体绩效、能力和行为的全面反馈。这种评估方法不仅涵盖了传统的上级评价&#xff0c;还包括同级、下级、自我评价以及客户或外部利益相关者的反馈。 一、360度评估的应用场景 员工绩效评估&#xff1a;360度评…

【PostgreSQL内核学习(二十二)—— 执行器(ExecutePlan)】

执行器&#xff08;InitPlan&#xff09; 概述ExecutePlan 函数ExecProcNode 函数 总结 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力求遵循合理使用原则&#xff0c;并在适用的情况下注明引用来…

超详细!4小时开发一个SpringBoot+vue前后端分离博客项目!!

超详细&#xff01;4小时开发一个SpringBootvue前后端分离博客项目&#xff01;&#xff01; 前后端分离项目 文章总体分为2大部分&#xff0c;Java后端接口和vue前端页面&#xff0c;比较长&#xff0c;因为不想分开发布&#xff0c;真正想你4小时学会&#xff0c;哈哈。 先…

【自学笔记】01Java基础-07面向对象基础-04接口与内部类详解

记录学习Java基础中有关接口类和内部类的知识。 1 接口 interface 关键字用于定义接口类&#xff0c;接口类是一系列方法的声明&#xff0c;一般只有方法的特征没有方法的实现&#xff0c;因此可以被不同的类接入实现&#xff0c;而这些实现可以具有不同的行为&#xff08;功…

Graham扫描凸包算法

凸包&#xff08;Convex Hull&#xff09;是包含给定点集合的最小凸多边形。凸包算法有多种实现方法&#xff0c;其中包括基于递增极角排序、Graham扫描、Jarvis步进法等。下面&#xff0c;我将提供一个简单的凸包算法实现&#xff0c;基于Graham扫描算法。 Graham扫描算法是一…

多级缓存架构(一)项目初始化

文章目录 一、项目克隆二、数据库准备三、项目工程准备 一、项目克隆 克隆此项目到本地 https://github.com/Xiamu-ssr/MultiCache 来到start目录下&#xff0c;分别有以下文件夹 docker&#xff1a;docker相关文件item-service&#xff1a;springboot项目 二、数据库准备 …

Ncast盈可视高清智能录播系统busiFacade RCE漏洞(CVE-2024-0305)

产品介绍 Ncast盈可视高清智能录播系统是一套新进的音视频录制和播放系统&#xff0c;旨在提供高质量&#xff0c;高清定制的录播功能。 漏洞描述 广州盈可视电子科技有限公司的高清智能录播系统存在信息泄露漏洞(CVE-2024-0305)&#xff0c;攻击者可通过该漏洞&#xff0c;…

Sectigo的DV通配符https

Sectigo是近些年发展比较快速的CA认证机构&#xff0c;为了提升审核效率&#xff0c;在全国成立了审核机构&#xff0c;亚太审核中心的成立加快了Sectigo旗下的https证书的审核速度。Sectigo的https证书可以为网站安全提供有力支持&#xff0c;从而保护网站信息安全。今天就随S…

群狼调研(长沙神秘顾客公司)开展某品牌家纺神秘顾客调研

为评估某品牌家纺的产品品质、设计、服务、价格等情况。群狼调研&#xff08;长沙娱乐场所神秘顾客调查&#xff09;受客户委托在全国1500家门店进行神秘顾客调研。本次调研神秘顾客全部由群狼调研从累计的16年资源库中筛选出的有经验的人员&#xff0c;以普通消费者的身份进店…

3、深入解析Redis Cluster集群运维与核心原理

在今天的大规模分布式系统中&#xff0c;Redis Cluster已经成为了许多企业选择的分布式缓存方案之一。了解Redis Cluster的运维及核心原理对于确保系统的高可用性和性能至关重要。本文将深入探讨Redis Cluster集群的运维细节和核心原理&#xff0c;以帮助读者更好地理解和优化R…

常见的HTTP接口超时问题出现原因及解决办法

HTTP接口超时问题是指在HTTP请求发送到服务器后&#xff0c;由于等待服务器响应的时间超过了预设的超时时间&#xff0c;导致请求被中断。以下是可能导致HTTP接口超时问题的原因和解决方法&#xff1a; 网络延迟或不稳定&#xff1a;网络延迟或不稳定可能导致请求在传输过程中…

【STM32】STM32学习笔记-MPU6050简介(32)

00. 目录 文章目录 00. 目录01. MPU6050简介02. MPU6050参数03. MPU6050硬件电路04. MPU6050框图05. MPU6050常用寄存器06. 附录 01. MPU6050简介 •MPU6050是一个6轴姿态传感器&#xff0c;可以测量芯片自身X、Y、Z轴的加速度、角速度参数&#xff0c;通过数据融合&#xff0…

网站监测工具的极与极,Site24x7 与百川云

今天我们聊聊我用 Site24x7 的感受。对于有网站监测有需求的站长们来说&#xff0c;Site24x7 确实是个很强大的应用。但是它与百川云网站监测完全不一样&#xff0c;百川云网站监测是适合用中小微企业的交互极简的saas 应用&#xff0c;Site24x7 完全是另一个极端&#xff0c;适…

datax关系数据库插件设计和实现解释

背景 DataX是一个异构数据源离线同步工具&#xff0c;致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。解决异构数据源同步问题&#xff0c;DataX将复杂的网状的同步链路变成了星型数据链路&#xff0…

勒索家族瞄准制造业,亚信安全发布《勒索家族和勒索事件监控报告》

本周态势快速感知 本周&#xff08;2024年第二期&#xff09;全球共监测到勒索事件37起&#xff0c;事件数量持续下降&#xff0c;降至近半年最低值。 lockbit3.0仍然是影响最严重的勒索家族&#xff1b;akira和bianlian恶意家族也是两个活动频繁的恶意家族&#xff0c;需要注…

红帽认证 | 红帽认证分几级?红帽认证的证书含金量高吗?

红帽认证是IT领域中备受关注的一种认证&#xff0c;它由红帽公司推出&#xff0c;旨在证明持证者在Linux操作系统方面的技能和知识。 那么&#xff0c;红帽认证分几级&#xff1f;红帽认证的证书含金量高吗&#xff1f;下面将详细介绍红帽认证的级别和证书含金量。 01 红帽认证…

KubeSphere 在 vsleem 的落地实践

作者&#xff1a;方忠&#xff0c;苏州威视通智能科技有限公司技术经理&#xff0c;开源技术爱好者&#xff0c;长期活跃于 dromara 开源社区并参与贡献。 公司介绍 公司简介 苏州威视通智能科技有限公司&#xff0c;是一家全球领先的全景 AI 平台提供商&#xff0c;结合极致…

1.15作业

使用计数型信号量设计&#xff1a;生产者和消费者模型 总结今天学习的API函数&#xff0c;写出函数参数和返回值的意思&#xff0c;并且说明函数功能 创建队列 osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_si…

GBASE日期计算

在进行数据迁移的过程中&#xff08;DB2–>GBASE&#xff09;涉及到日期计算函数的改写&#xff1a; 原式子如下&#xff1a; SELECT TIMESTAMP(1900-01-01) INT(LEFT(MAX(DB_TIMESTAMP),3)) YEAR INT(SUBSTR(MAX(DB_TIMESTAMP),4,3)) -1) DAY INT(SUBSTR(MAX(DB_TIMEST…

Java项目:121SSM记账管理系统

博主主页&#xff1a;Java旅途 简介&#xff1a;分享计算机知识、学习路线、系统源码及教程 文末获取源码 一、项目介绍 记账管理系统基于SpringSpringMVCMybatis开发&#xff0c;系统主要功能如下&#xff1a; 收入项管理 支出项管理 收入方式管理 支出方式管理 添加收入…