React 19.2.0 发布
React 19.2.0 现已发布,具体更新内容如下:
React 的新功能
<Activity />
<Activity>
允许你将应用程序拆分为“活动”,这些活动可以被控制和优先排序。你可以使用 Activity 作为有条件地渲染应用程序部分的替代方法:
// Before
{isVisible && <Page />}
// After
<Activity mode={isVisible ? 'visible' : 'hidden'}>
<Page />
</Activity>
在 React 19.2 中,Activity 支持两种模式:visible
和hidden
。
hidden
:隐藏子项,卸载效果,并推迟所有更新,直到 React 没有剩余工作可做。visible
:显示子项、安装效果并允许正常处理更新。
这意味着你可以预渲染并继续渲染应用程序的隐藏部分,而不会影响屏幕上可见内容的性能。可以使用 Activity 来渲染应用中用户接下来可能导航到的隐藏部分,或者保存用户导航离开的部分的状态。这有助于通过在后台加载数据、CSS 和图片来加快导航速度,并允许返回导航保留输入字段等状态。
将来,开发团队计划为 Activity 添加更多模式以适应不同的用例。
有关如何使用 Activity 的示例,可查看Activity 文档。
useEffectEvent
使用 useEffect
时,一个常见的模式是通知应用程序代码关于来自外部系统的某种“事件”。例如,当聊天室连接时,你可能希望显示一个通知:
function ChatRoom({ roomId, theme }) {
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.on('connected', () => {
showNotification('Connected!', theme);
});
connection.connect();
return () => {
connection.disconnect()
};
}, [roomId, theme]);
// ...
上述代码的问题在于,任何在这样的“事件”中使用的值的更改都会导致周围 Effect 重新运行。例如,更改 theme
会导致聊天室重新连接。对于与 Effect 逻辑本身相关的值(如 roomId
)来说,这很合理,但对于 theme
来说则不合理。
为了解决这个问题,大多数用户只是禁用 lint 规则并排除依赖项。但这可能导致错误,因为如果以后需要更新 Effect,linter 就无法帮助你保持依赖项的更新。
使用 useEffectEvent
,你可以将这种逻辑的“事件”部分从发出它的 Effect 中分离出来:
function ChatRoom({ roomId, theme }) {
const onConnected = useEffectEvent(() => {
showNotification('Connected!', theme);
});
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.on('connected', () => {
onConnected();
});
connection.connect();
return () => connection.disconnect();
}, [roomId]); // ✅ All dependencies declared (Effect Events aren't dependencies)
// ...
与 DOM 事件类似,Effect 事件总是“看到”最新的 props 和 state。
Effect 事件不应声明在依赖数组中。你需要升级到 eslint-plugin-react-hooks@6.1.1
,以便 linter 不会尝试将其作为依赖项插入。请注意,Effect 事件只能在同一组件或 Hook 中声明“它们”的 Effect。这些限制由 linter 验证。
cacheSignal
cacheSignal
仅适用于React Server Components。
cacheSignal
让你知道cache()
生命周期何时结束:
import {cache, cacheSignal} from 'react';
const dedupedFetch = cache(fetch);
async function Component() {
await dedupedFetch(url, { signal: cacheSignal() });
}
这允许你在结果不再用于缓存时清理或中止工作,例如:
- React 已成功完成渲染
- 渲染已中止
- 渲染失败
欲了解更多信息,参阅cacheSignal
文档。
Performance Tracks
React 19.2 为 Chrome DevTools 性能配置文件添加了一组新的自定义轨道,以提供有关 React 应用程序性能的更多信息:
React Performance Tracks 文档解释了轨道中包含的所有内容。
调度器
调度器跟踪显示 React 在不同优先级下正在做什么,例如“阻塞”用于用户交互,或“过渡”用于 startTransition 内的更新。在每个跟踪中,你会看到正在进行的工作类型,例如安排更新的事件,以及该更新的渲染发生的时间。
还显示信息,例如当更新因等待不同优先级而被阻塞,或者当 React 在继续之前等待绘制时。调度器跟踪帮助你理解 React 如何将你的代码拆分为不同的优先级,以及完成工作的顺序。
参阅 Scheduler track 文档以了解所包含的所有内容。
组件
组件跟踪显示 React 正在处理的组件树,无论是为了渲染还是运行效果。在里面,你会看到诸如“Mount”标签,表示子组件挂载或效果挂载,或者“Blocked”标签,表示由于让步给 React 外部的工作而阻止渲染。
组件跟踪帮助你了解组件何时被渲染或运行效果,以及完成该工作的所需时间,以帮助识别性能问题。
参阅组件轨道文档以查看包含的所有内容。
React DOM 的新功能
部分预渲染
在 19.2 中新增了一个能力,可以在提前渲染应用的一部分,然后稍后恢复渲染。这个功能称为“部分预渲染”,允许你预先渲染应用的静态部分并从 CDN 提供,然后稍后恢复渲染外壳以填充动态内容。
要预渲染一个稍后可恢复的应用,首先调用 prerender 并传入一个 AbortController:
const {prelude, postponed} = await prerender(<App />, {
signal: controller.signal,
});
// Save the postponed state for later
await savePostponedState(postponed);
// Send prelude to client or CDN.
然后,可以将prelude
shell 返回给客户端,稍后调用resume
“resume”到 SSR 流:
const postponed = await getPostponedState(request);
const resumeStream = await resume(<App />, postponed);
// Send stream to client.
或者可以调用resumeAndPrerender
resume 来获取 SSG 的静态 HTML:
const postponedState = await getPostponedState(request);
const { prelude } = await resumeAndPrerender(<App />, postponedState);
// Send complete HTML prelude to CDN.
有关更多信息,参阅新 API 的文档:
react-dom/server
resume
:用于 Web 流。resumeToPipeableStream
用于 Node 流。
react-dom/static
resumeAndPrerender
用于 Web 流。resumeAndPrerenderToNodeStream
用于 Node 流。
此外,预渲染 API 现在返回一个postpone
状态以传递给resume
API。
显著变化
SSR 中的 Suspense 边界批处理
修复了一个行为性错误,该错误导致 Suspense 边界会根据是在客户端渲染还是从服务器端渲染流式传输而显示不同的内容。从 19.2 开始,React 将在短时间内批量显示服务器渲染的 Suspense 边界,以允许更多内容一起显示并与客户端渲染的行为保持一致。
以前,在流式传输服务器端渲染期间,Suspense 内容会立即替换后备内容。
在 React 19.2 中,Suspense 边界会在短时间内进行批处理,以允许一起揭示更多内容。
此修复还为支持 SSR 中的 <ViewTransition>
准备了应用程序。通过一起揭示更多内容,动画可以在更大的内容批次中运行,并避免链式动画内容流接近在一起。
注意:React 使用启发式方法来确保节流不会影响核心网页指标和搜索排名。例如,如果页面总加载时间接近 2.5 秒(这是被认为是 LCP 的“良好”时间),React 将停止批处理并立即揭示内容,以确保节流不会成为错过指标的原因。
SSR:Node 的 Web Streams 支持
React 19.2 增加了对 Web Streams 的支持,用于在 Node.js 中流式传输 SSR:
renderToReadableStream
现在可用于 Node.jsprerender
现在可用于 Node.js
以及新的resume
API:
resume
适用于 Node.js。resumeAndPrerender
适用于 Node.js。
在 Node.js 中优先使用 Node Streams 进行服务器端渲染
在 Node.js 环境中,官方仍然强烈建议使用 Node Streams API:
这是因为 Node Streams 比 Node 中的 Web Streams 快得多,并且 Web Streams 默认不支持压缩,导致用户意外错过了流式传输的好处。
eslint-plugin-react-hooks
v6
还发布了eslint-plugin-react-hooks@6.1.1
,默认情况下在 recommended
预设中使用扁平配置,并为新的 React 编译器驱动规则启用选择加入。
要继续使用旧配置,可以更改为recommended-legacy
:
- extends: ['plugin:react-hooks/recommended']
+ extends: ['plugin:react-hooks/recommended-legacy']
查看eslint-plugin-react-hooks
变更日志以获取完整的变更列表。
更新默认useId
前缀
在 19.2 中,将默认useId
前缀从:r:
(19.0.0) 或«r»
(19.1.0) 更新为_r_
。
变更日志
其他显著变化
值得注意的错误修复
react
:将上下文字符串化为“SomeContext”而不是“SomeContext.Provider” #33507react
:修复 popstate 事件中的无限 useDeferredValue 循环#32821react
:修复将初始值传递给 useDeferredValue 时出现的错误#34376react
:修复提交带有 Client Actions 的表单时的崩溃问题#33055react
:如果 dehydrated suspense boundaries 重新暂停,则隐藏/显示其内容 #32900react
:避免热重载期间宽树上的堆栈溢出#34145react
:改进各处的组件堆栈#33629、#33724、#32735、#33723react
:修复 React.lazy-ed 组件中 React.use 的一个错误#33941react-dom
:使用 ARIA 1.3 属性时停止警告#34264react-dom
:修复 Suspense fallbacks 中深度嵌套 Suspense 的错误#33467react-dom
:在渲染过程中发生中止后进行挂起操作时,避免出现卡顿现象#34192
有关更改的完整列表,可参阅变更日志。
为您推荐相关文章:
同类文章推荐: