React 18 快速指南及核心概念讲解
React 18 为并发渲染 API 奠定了基础,未来的 React 功能将以此为基础构建。此版本专注于性能改进和渲染引擎的更新。
快速指南
类别 | 特征 |
---|---|
概念 | 并发反应 |
特征 | 服务器上的自动批处理、转换和暂停 |
蜜蜂 | 创建根、水合根、渲染管道流、渲染可读流 |
钩子 | useId、useTransition、useDeferredValue、useSyncExternalStore、useInsertionEffect |
更新 | 严格模式 |
已弃用/不鼓励 | ReactDOM.render,renderToString |
如何升级到 React 18
-
从 npm 或 yarn 安装 React 18 和 React DOM
npm install react react-dom
-
使用
createRoot
而不是render
在您的 index.js 中,更新ReactDOM.render
以ReactDOM.createRoot
创建根,并使用根呈现您的应用程序 -
React 17 -
import ReactDOM from 'react-dom';
import App from 'App';
const container = document.getElementById('app');
ReactDOM.render(<App />, container);
React 18 -
import ReactDOM from 'react-dom';
import App from 'App';
const container = document.getElementById('app');
// create a root
const root = ReactDOM.createRoot(container);
//render app to root
root.render(<App />);
核心概念:并发
为了理解并发性,让我们考虑一下来自 React 18 工作组讨论的 Dan Abramov 的这个例子:
假设我们需要给两个人打电话——Alice 和 Bob。在非并发设置下,我们一次只能进行一个通话——我们会先给 Alice 打电话,然后结束通话,再给 Bob 打电话。如果通话时间短,这种做法还行,但如果与 Alice 的通话需要长时间等待(例如保持通话),这可能会浪费时间。
在并发设置中,我们可以先给 Alice 打电话,一旦被搁置,我们就可以再给 Bob 打电话。这并不意味着我们同时与两个人通话,而是意味着我们可以同时进行两个或多个并发通话,并决定哪个通话更重要。
同样,在支持并发渲染的 React 18 中,React 可以中断、暂停、恢复或放弃渲染。这使得 React 即使在繁重的渲染任务中也能快速响应用户交互。在 React 18 之前,渲染是一个单一、不间断的同步事务,一旦渲染开始,就无法中断。
并发是 React 渲染机制的一项基础更新。并发允许 React 中断渲染。React 18 引入了并发渲染的基础,并发渲染支持 Suspense、流式服务器渲染和过渡等新功能。
新功能:自动配料
React 18 具有自动批处理功能。为了理解批处理,让我们考虑同一个 React 工作组讨论中的杂货店购物示例。假设您正在做意大利面作为晚餐。如果您要优化您的购物之旅,您会列出所有需要购买的食材,然后前往杂货店,并在一次旅程中购买所有食材。这就是批处理。如果没有批处理,您会开始做饭,发现您需要一种食材,然后去杂货店购买食材,回来继续做饭,发现您需要另一种食材,然后去杂货店,让自己发疯。
在 React 中,批处理有助于减少状态更改时调用 时发生的重新渲染次数setState
。以前,React 在事件处理程序中批量更新状态,例如:
const handleClick = () => {
setCounter();
setActive();
setValue();
}
//re-rendered once at the end.
但是,事件处理程序之外发生的状态更新不会被批处理。例如,如果你有一个 Promise 或进行网络调用,状态更新就不会被批处理。例如:
fetch('/network').then( () => {
setCounter(); //re-rendered 1 times
setActive(); //re-rendered 2 times
setValue(); //re-rendered 3 times
});
//Total 3 re-renders
显而易见,这性能不佳。React 18 引入了自动批处理功能,允许所有状态更新(即使在 Promise、setTimeouts 和事件回调中)进行批处理。这显著减少了 React 在后台需要执行的工作。React 会等待微任务完成后再重新渲染。
React 中开箱即用地提供自动批处理功能,但如果您想退出,可以使用flushSync
。
新功能:过渡
过渡效果可用于标记不需要紧急资源进行更新的 UI 更新。例如:在预输入字段中输入内容时,会发生两件事:一个是闪烁的光标,用于显示正在输入内容的视觉反馈;另一个是在后台执行搜索功能,用于搜索输入的数据。
向用户显示视觉反馈非常重要,因此也很紧急。搜索不那么紧急,因此可以标记为非紧急。这些非紧急的更新被称为过渡。通过将非紧急的 UI 更新标记为“过渡”,React 就能知道哪些更新需要优先处理,从而更容易优化渲染并摆脱陈旧的渲染。
可以使用 将更新标记为非紧急 startTransition
。以下是使用过渡效果标记的 TypeAhead 组件的示例 -
import { startTransition } from 'react';
// Urgent: Show what was typed
setInputValue(input);
// Mark any non-urgent state updates inside as transitions
startTransition(() => {
// Transition: Show the results
setSearchQuery(input);
});
它与 debouncing 或 setTimeout 有何不同?
- startTransition 与 setTimeout 不同,会立即执行。
- setTimeout 具有保证的延迟,而 startTransition 的延迟取决于设备的速度和其他紧急渲染。
- 与 setTimeout 不同,startTransition 更新可以被中断,并且不会冻结页面。
- 当标记为startTransition时,React可以为您跟踪待处理状态。
新功能:服务器上的悬念
React 18 引入了 -
- 使用 Suspense 在服务器上进行代码拆分
- 服务器上的流式渲染
客户端渲染与服务器渲染
在客户端渲染的应用中,你会从服务器加载页面的 HTML 以及运行页面所需的所有 JavaScript,并使其具有交互性。但是,如果你的 JavaScript 包很大,或者你的网络连接速度很慢,这个过程可能会花费很长时间,用户需要等待页面变得可交互或看到有意义的内容。
客户端渲染流程图。来源:Shaundai Person 在 React Conf 2021 上发表的“使用 Suspense 进行流式服务器渲染” https://www.youtube.com/watch?v=pj5N-Khihgc
为了优化用户体验,避免用户坐在空白屏幕上,我们可以使用服务器渲染。服务器渲染是一种技术,它将 React 组件的 HTML 输出渲染到服务器上,并从服务器发送 HTML。这使得用户能够在 JS 包加载过程中以及应用开始交互之前看到一些 UI。有关客户端渲染与服务器渲染的详细概述,请查看 Shaundai Person 在 React Conf 2021 上的演讲。
服务端渲染流程图。来源:Shaundai Person 在 React Conf 2021 上发表的“使用 Suspense 进行流式服务端渲染” https://www.youtube.com/watch?v=pj5N-Khihgc
服务器渲染进一步增强了用户加载页面的体验,减少了交互的时间。
现在,如果你的应用除了一部分之外,大部分都很快,该怎么办?也许这部分数据加载很慢,或者可能需要下载大量的 JS 才能进行交互。
在 React 18 之前,这部分可能成为应用程序的瓶颈,并增加渲染组件所需的时间。一个缓慢的组件可能会拖慢整个页面的速度。这是因为服务器渲染要么全部执行,要么全部不执行——你无法告诉 React 延迟加载缓慢的组件,也无法告诉 React 发送其他组件的 HTML。
React 18 新增了对服务端 Suspense 的支持。借助 Suspense,你可以将应用中运行缓慢的部分包裹在 Suspense 组件中,从而告诉 React 延迟加载该缓慢组件。此外,它还可以用于指定加载过程中显示的加载状态。
在 React 18 中,一个缓慢的组件不必拖慢整个应用的渲染速度。使用 Suspense,你可以告诉 React 首先发送其他组件的 HTML 以及占位符的 HTML(例如加载旋转按钮)。然后,当缓慢的组件准备就绪并获取其数据后,服务器渲染器会将其 HTML 弹出到同一个流中。
这样,用户可以尽早看到页面的框架,并随着更多 HTML 代码的加载逐渐看到更多内容。所有这些都发生在页面加载任何 JS 或 React 代码之前,从而显著提升用户体验并减少用户感知的延迟。
严格模式
React 18 中的严格模式将模拟组件在先前状态下的挂载、卸载和重新挂载。这为未来的可复用状态奠定了基础,React 可以通过在卸载之前使用相同的组件状态重新挂载树来立即挂载上一个屏幕。严格模式将确保组件能够适应多次挂载和卸载的影响。
来源 -
- React RFC
- 我之前的 React 18 帖子
- React V18 博客
- React Conf 2021 - 面向应用开发者的 React
- React Conf 2021 - 使用 Suspense 进行流式服务器渲染
如果您喜欢这篇文章,请点个❤️,以便其他人也能找到它。
- 如需更多常见提示,请关注 Twitter
- 想要直接在收件箱中收到此类文章吗?