作者:
React 团队
译者:
林语冰
资源:React 官方博客[1]
免责声明:活人翻译,略有删改,仅供粉丝参考!
00. Hello World
大家好,我是大家的 林语冰
。
React 官方博客的上半部分主要共享了 React 19 新增的功能,比如 RSC 或 use API 等,而本文主要共享 React 19 相对于旧版所做的 DX 优化或其他改进。
01. ref 作为 prop
React 19 可以访问 ref
作为函数组件的 prop:
jsx
function MyInput({placeholder, ref}) {
return <input placeholder={placeholder} ref={ref} />
}
<MyInput ref={ref} />
新版函数组件不再需要 forwardRef
。
注意,传递给类的 refs
不会作为 props 传递,因为它们引用了组件实例。
02. 作为 provider
React 19 可以把 <Context>
渲染为 provider,而不是 <Context.Provider>
:
jsx
const ThemeContext = createContext('');
function App({children}) {
return (
<ThemeContext value="dark">
{children}
</ThemeContext>
);
}
新的 Context provider 可以使用 <Context>
。
03. refs 的清理函数
现在支持从 ref
回调返回清理函数:
jsx
<input
ref={(ref) => {
// 创建 ref
// 当元素从 DOM 中移除时,
// 现在返回清理函数来重置 ref
return () => {
// 清理 ref
};
}}
/>
当组件卸载时,React 会调用从 ref
回调返回的清理函数。这适用于 DOM 引用、类组件的引用和 useImperativeHandle
。
以前,React 在卸载组件时会调用带有 null
的 ref
函数。现在,如果 ref
返回清理函数,React 会跳过此步骤。
由于引入了 ref
清理函数,从 ref
回调返回任何其他内容现在都会被 TS 拒绝。
解决方案是停用隐式返回,比如:
diff
- <div ref={current => (instance = current)} />
+ <div ref={current => {instance = current}} />
04. useDeferredValue 的初始值
useDeferredValue
添加了一个 initialValue
选项:
jsx
function Search({deferredValue}) {
// 初始渲染时值为 ''
// 重渲染会使用 deferredValue 调度。
const value = useDeferredValue(deferredValue, '');
return (
<Results query={value} />
);
}
如果提供了 initialValue
,useDeferredValue
会将其作为组件初始渲染的 value
返回,并使用返回的 deferredValue
在后台调度重新渲染。
05. 支持文档元数据
React 19 支持在组件中原生渲染文档元数据标签:
jsx
function BlogPost({post}) {
return (
<article>
<title>{post.title}</title>
<meta name="keywords" content={post.keywords} />
</article>
);
}
当 React 渲染该组件时,它会识别 <title>
、<link>
和 <meta>
标记,并自动将它们提升到文档的<head>
部分。
06. 支持样式表
React 19 内置对样式表的支持。
如果你告诉 React 样式表的 precedence
,它会管理 DOM 中样式表的插入顺序,并确保在显示依赖这些样式规则的内容之前加载外部样式表。
jsx
function ComponentOne() {
return (
<Suspense fallback="loading...">
<link rel="stylesheet" href="foo" precedence="default" />
<link rel="stylesheet" href="bar" precedence="high" />
</Suspense>
)
}
在服务端渲染期间,React 会在 <head>
中包含样式表,这确保浏览器在加载之前不会绘制。如果样式表在我们开始流式传输之后被发现,React 会确保样式表插入到客户端的 <head>
中,然后再显示依赖该样式表的 Suspense 边界的内容。
在客户端渲染期间,React 会等待新渲染的样式表加载,然后再提交渲染。如果你从应用中的多个位置渲染此组件,React 只会在文档中包含一次样式表:
jsx
function App() {
return <>
<ComponentOne />
...
<ComponentOne />
// 不会导致 DOM 中出现重复样式表链接
</>
}
07. 支持异步脚本
React 19 更好地支持异步脚本,允许你在组件树中的任何位置、实际依赖脚本的组件内渲染它们,而无需管理重新定位和重复数据删除的脚本实例。
jsx
function MyComponent() {
return (
<div>
<script async={true} src="..." />
</div>
)
}
function App() {
<html>
<body>
<MyComponent>
...
<MyComponent>
// 不会导致 DOM 中的重复脚本
</body>
</html>
}
在所有渲染环境中,异步脚本都会被去重,这样即使脚本由多个不同的组件渲染,React 也只会加载并执行一次脚本。
08. 支持预加载资源
React 19 新增许多用于加载和预加载浏览器资源的 API,以便尽可能轻松地构建不受低效资源加载阻碍的出色体验。
这些 API 可用于通过将字体等其他资源的发现移出样式表加载来优化初始页面加载。
它们还可以通过预请求预期导航使用的资源列表,然后在单击甚至挂起时迫切预加载这些资源,从而加快客户端更新速度。
09. 支持自定义元素
React 19 增加了对 自定义元素[2] 的全面支持,因为旧版 React 将无法识别的 props 视为特性(attributes)而不是属性(properties)。
React 19 添加了对在客户端和 SSR 期间使用的属性的支持,策略如下:
- 服务器端渲染 :如果传递给自定义元素的 props 类型是
string
、number
等原始值或者值为true
,那么它们会渲染为属性。诸如object
、function
等非原始值或false
值的 props 会被省略。 - 客户端渲染:与自定义元素实例上的属性匹配的 props 会被赋值为属性(properties),否则会被赋值为特性(attributes)。
高潮总结
React 19 是 React 18 发布两年后再次升级的主版本,除了上一篇官方博客中分享的新功能外,还有本文涉及的开发体验和旧版功能的优化,升级新版时记得参考 迁移指南[3]。
我是大家的 林语冰
👨💻,欢迎持续 关注,随时了解海内外前端开发的最新情报。
谢谢的大家点赞、留言和友情转发,我们下期再见~👍
参考文献
[1] React 官方博客: react.dev/blog/2024/1...
[2] 自定义元素: custom-elements-everywhere.com
[3] 迁移指南: react.dev/blog/2024/0...