React 18 - 新功能和改进策略
3月8日,React团队发布了React 18 RC(候选版本)。最新版本带来了一系列新功能,这些功能将彻底改变许多应用程序中的编码模式。此外,它还带来了一些性能改进,我将在本篇博客中详细介绍。
并发
并发是系统的一种属性,指多个进程同时执行,这些进程之间可能交互,也可能不交互。太复杂了?我们来分解一下。假设有一场比赛正在进行。并发指的是有多少人在一条平行的跑道上进行单场比赛。
并发是 React 18 引入的新功能。它是一种新的幕后机制,使 React 能够同时准备多个版本的 UI。
在这种机制下,与以往的情况不同,React 可以启动渲染,在中途暂停执行某些关键任务,然后再次恢复渲染。唯一需要注意的是,它也可能完全放弃正在进行的渲染。即使渲染被中断,React 也能保证 UI 的一致性。
这使得 React 能够在后台准备屏幕 - 而不会阻塞新线程!
Suspense 用于服务器端渲染
React 已经在 Next.js、Relay、Hydrogen 和 Remix 等服务器端渲染框架中引入了 Suspense 功能。React 18 引入了:使用 Suspense
在服务器上进行代码拆分,以及
在服务器上进行流式渲染。
自动配料
批处理是 React 将多个状态更新分组到一次重新渲染中以实现更好的性能优化的现象。

在 React 18 之前,基于 React 的事件处理器会执行批量更新。然而,对于Promise、setTimeouts、原生事件处理器或其他事件,则不会执行批量更新。React 18 也会针对上述情况执行自动批量更新。
让我们用代码来理解这一点。
设置超时(()=> { 设置计数(计数 => 计数 + 1); 设置标志(标志 => !标志); // React 最终只会重新渲染一次(这就是批处理!) }, 1000);
同样,上述代码的行为与此相同:
获取(/*...*/).然后(()=> { 设置计数(计数器 => 计数器 + 1); 设置标志(标志 => !标志); // React 最终只会重新渲染一次(这就是批处理!) })
如果你不想批量处理,可以使用ReactDOM.flushSync()
。让我们通过一些代码来理解
从“react-dom”导入{flushSync};//注意:react-dom,而不是react 函数handleFlushesClick(){ flushSync(() => { 设置计数器(计数器 => 计数器 + 1); }); // React 现在已经更新了 DOM flushSync(() => { 设置标志(标志 => !标志); }); // React 现在已经更新了 DOM }
过渡
此功能区分紧急更新和非紧急更新。紧急更新是指需要立即响应的更新。紧急更新包括点击、按下、输入等需要立即响应或用户希望 UI 立即响应的操作。
屏幕上不会显示任何中间值。
现实生活中的例子
举一个现实生活中的例子,让我们设想一个带去抖动功能的预输入功能。现在,当你输入内容时,你希望输入框能够反映你输入的值。但是,你希望结果立即出现吗?当然不是!它会先去抖动,然后你才能得到结果。所以,从你输入内容到得到建议之间会有一些过渡时间。这段时间将用于过渡。
通常,为了获得最佳用户体验,单个用户输入应该导致紧急和非紧急更新。
从'react'导入{startTransition}; // 紧急:显示已输入的内容 设置输入值(输入);` // 将内部的任何状态更新标记为转换 开始过渡(()=> { // 过渡:根据输入显示自我建议 价值 设置搜索查询(输入); });
另一个实时示例
const [isPending,startTransition] = useTransition()
这里的 useTransition 钩子有 2 个解构的参数。
isPending
:表示 UI 更新是否仍处于过渡状态
startTransition
:执行交易代码的函数。
函数handleClick(){ 开始过渡(()=> { 设置Tab('评论'); }); }
当您想要从“照片”选项卡切换到“评论”选项卡时,会调用此函数。
<Suspense fallback={<Spinner />}>
<div style={{ opacity: isPending ? 0.8 : 1 }}>
{tab === 'photos' ? <Photos /> : <Comments />}
</div>
</Suspense>
在过渡阶段,当 React 准备新的 UI 时,带有照片 UI 的选项卡现在将以 80% 的不透明度显示给用户,以提供平滑的过渡视图。
React 中的严格模式
开发服务器中的严格模式在 React 18 中带来了一些有趣的变化。这种模式本质上为 React 提供了开箱即用的性能。
每当组件第一次安装时,此新检查将自动卸载并重新安装每个组件,并在第二次安装时恢复先前的状态。
现在安装过程中发生的一系列事件:
一、React挂载组件。
- 布局效果已创建。
- 效果已产生。
II. React 模拟卸载组件。
- 布局效果被破坏。
- 效果被破坏。
III. React 使用之前的状态模拟安装组件。
- 布局效果已创建。
- 已产生效果。'
卸载期间,会发生以下事件
一、Layout效果破坏,Effect效果破坏。
新钩子
a. useId
useId 是一个新的钩子,用于在客户端和服务器端生成**唯一 ID ,同时避免数据不匹配。它会生成一个**包含 : 的唯一字符串,该字符串不会与 CSS 选择器冲突,并且querySelectorAll
*
您还可以将 userId 与 identifierPrefix 一起使用,以防止在多根应用中发生冲突。对于同一组件中的多个 ID,请使用相同的 ID 附加后缀。
b. useDeferredValue
useDeferredValue 可以让你推迟重新渲染树中非紧急部分。还记得我们讨论过非紧急渲染吗?它没有固定的时间延迟,因此 React 会在第一次渲染反映到屏幕上后立即尝试延迟渲染。
c. useSyncExternalStore
useSyncExternalStore 是一个新的钩子,它通过强制同步更新外部存储来支持并发读取。它消除了在实现对外部数据源的订阅时使用 useEffect 的需要。
代码片段:
const state = useSyncExternalStore(订阅,getSnapshot [,getServerSnapshot]);
subscribe
:用于注册每当存储发生变化时调用的回调函数。getSnapshot
:用于返回存储当前值的函数。getServerSnapshot
:用于返回服务器渲染期间使用的快照的函数。
d. useInsertionEffect
useInsertionEffect(didUpdate);
useInsertionEffect 是一个新的钩子,它允许 CSS-in-JS 库解决在渲染过程中注入样式的性能问题。此钩子将在 DOM 发生变异之后、布局效果读取新布局之前运行。
这个钩子将有助于计算与并发重新渲染同步的布局。
结论
还有一些其他小而重要的更新 - 例如使用createRoot()
钩子而不是ReactDOM.render
。此方法将用于渲染 DOM 元素并使用 umountroot.unmount()
除此之外,React 还为使用renderToPipeableStream
& 的服务器提供流式 Suspense 支持renderToReadableStream
React 开发者持续关注此发布版本的增强、改进和一些错误修复。更新过程并不细致,一个上午就能完成。所以,应用程序开发者们还在等什么?让我们升级我们的库,开始工作吧!向 React 团队致敬!
文章来源:https://dev.to/officialbidisha/react-18-to-the-rescue-38g3