React 19新特性和更新介绍 03 - 改进和增强
React 19 于 2024 年 4 月 25 日正式发布,标志着一个重要的里程碑。
此版本带来了各种新功能和改进,以增强开发人员体验和应用程序性能。
React 19 中的改进和增强
1. Ref 作为 Prop
React 19 对 refs 进行了重大改进:
现在您可以将其作为 props 传递给功能组件(functional components)。这在大多数情况下消除了对 forwardRef 高阶组件 (HOC) 的需求。
新的函数组件(function components)将不再需要 forwardRef,我们将发布 codemod 来自动更新您的组件以使用新的 ref prop。
在未来的版本中,我们将弃用并删除 forwardRef。
关键改进
- 使用 Refs 的更简单的功能组件:以前,功能组件无法直接将 refs 作为 props 接收。使用 React 19,您可以使用标准 prop 语法传递 refs,使功能组件在与 DOM 元素交互时更加灵活。
- 减少样板:通过消除对 forwardRef 的需求,您的代码变得更干净、更简洁。这简化了组件创建并提高了可读性。
- 向后兼容性:对于需要将 ref 传递给类组件或深度嵌套的功能组件层次结构的场景,React 19 仍然支持 forwardRef HOC。使用 forwardRef 的现有代码将继续按预期运行。
示例:
<MyInput ref={ref} />
function MyInput({placeholder, ref}) {return <input placeholder={placeholder} ref={ref} />
}
2. Hydration Error 的差异
我们通过改进错误报告的方式,使发现 React 中的错误变得更加容易。之前,它只会显示一堆错误,而不会解释出了什么问题。现在,它会显示一条清晰的消息,详细说明不同之处。
3. Context as a Provider
在 React 19 中,你可以将 <Context>
渲染为 Provider ,而不是 <Context.Provider>
示例:
const ThemeContext = createContext('');function App({ children }) {return (<ThemeContext value="dark">{children}</ThemeContext>);
}
4. Refs 的清理函数
React 19 为 refs 引入了一项新功能:能够从 ref 回调中返回清理函数。
这允许在组件卸载时更好地管理资源。
主要改进
- 自动清理:当组件卸载时,React 将自动调用从 ref 回调返回的清理函数。这可确保正确清理与 ref 相关的资源,例如删除事件侦听器、关闭订阅或释放内存。
- 提高代码可读性:通过在 ref 回调中明确定义清理逻辑,您的代码变得更易读和更易于维护。您可以在创建 ref 的同时跟踪资源管理。
- 减少内存泄漏:通过确保正确清理,您可以防止 React 应用程序中的内存泄漏。这对于长时间运行的组件或处理外部资源的组件尤其重要。
示例:
<inputref={(ref) => {// ref created// NEW: return a cleanup function to reset// the ref when element is removed from DOM.return () => {// ref cleanup};}}
/>
React 19 通过一项新功能简化了文档元数据(标题、描述、元标记)的管理:内置对文档元数据的支持。此改进简化了 SEO(搜索引擎优化)并增强了对文档 部分的控制。
主要改进
- 专用组件:React 19 引入了 DocumentHead 组件。这允许您在 React 组件中声明性地定义元数据元素。与传统方法相比,这种方法改善了代码组织和可读性。
- 简化的 SEO 管理:通过在 DocumentHead 中集中元数据管理,您可以轻松地直接在 React 应用程序中控制标题、描述和其他与 SEO 相关的元素。这使 SEO 管理更加高效。
- 减少样板:使用 DocumentHead 无需手动操作字符串或复杂的解决方法来更新文档元数据。这可以使代码更干净、更简洁。
在 HTML 中,文档元数据标签(如
、<link> 和 <meta>)保留用于放置在文档的 <head> 部分中。在 React 中,决定哪些元数据适合应用的组件可能距离渲染 <head> 的位置非常远,或者 React 根本不渲染 <head>。过去,这些元素需要手动插入到效果中,或者通过 react-helmet 等库插入,并且在服务器渲染 React 应用程序时需要小心处理。</p>
<p>在 React 19 中,我们添加了对在组件中原生渲染文档元数据标签的支持:</p>
<p>当 React 渲染此组件时,它将看到 <title>、<link> 和 <meta> 标签,并自动将它们提升到文档的 <head> 部分。通过原生支持这些元数据标签,我们能够确保它们适用于仅限客户端的应用程序、流式 SSR 和服务器组件。</p>
<pre><code class="language-jsx">
function BlogPost({post}) {return (<article><h1>{post.title}</h1><title>{post.title}</title><meta name="author" content="Josh" /><link rel="author" href="https://twitter.com/joshcstory/" /><meta name="keywords" content={post.keywords} /><p>Eee equals em-see-squared...</p></article>);
}</code></pre>
<h2 id="6-样式表支持">6. 样式表支持</h2>
<p>React 19 为管理 React 组件中的样式表引入了重大改进:内置样式表支持,包括外部链接样式表和内联样式。此增强功能简化了样式的应用方式,并确保在不同场景中正确呈现。</p>
<p>主要改进</p>
<p>改进的样式表管理:React 19 控制 DOM 中的样式表加载和插入顺序。这消除了在呈现组件之前应用样式的潜在问题。<br>
声明性控制:您可以直接在组件中指定样式表依赖项,从而更轻松地管理特定于特定组件或组件组的样式。<br>
减少样板:React 处理样式表管理的复杂性,减少了对手动解决方法或复杂样式库的需求。</p>
<p>由于样式优先规则,样式表(包括外部链接 (<link rel="stylesheet" href="...">) 和内联 (<style>...</style>))都需要在 DOM 中仔细定位。构建允许在组件内组合的样式表功能非常困难,因此用户通常要么将所有样式加载到可能依赖它们的组件之外,要么使用封装了这种复杂性的样式库。</p>
<p>在 React 19 中,我们解决了这种复杂性,并通过内置对样式表的支持,提供与客户端并发渲染和服务器流式渲染的更深入集成。如果您告诉 React 样式表的优先级,它将管理样式表在 DOM 中的插入顺序,并确保在显示依赖于这些样式规则的内容之前加载样式表(如果是外部的)。</p>
<p>在服务器端渲染期间,React 会将样式表包含在 <head> 中,这可确保浏览器在加载之前不会进行绘制。如果在我们开始流式传输之后才发现样式表,React 将确保在显示依赖于该样式表的 Suspense 边界的内容之前,将样式表插入到客户端的 <head> 中。</p>
<p>示例:</p>
<pre><code>
function ComponentOne() {return (<Suspense fallback="loading..."><link rel="stylesheet" href="foo" precedence="default" /><link rel="stylesheet" href="bar" precedence="high" /><article class="foo-class bar-class">{...}</article></Suspense>)
}function ComponentTwo() {return (<div><p>{...}</p><-- 通过 precedence 属性,will be inserted between foo & bar --><link rel="stylesheet" href="baz" precedence="default" /> </div>)
}</code></pre>
<h2 id="7-支持异步脚本">7. 支持异步脚本</h2>
<p>React 19 为处理组件中的异步脚本带来了令人欣喜的改进:更好地支持异步脚本。这简化了管理组件树中异步加载且可能以任何顺序加载的脚本。</p>
<p>主要改进</p>
<ul>
<li>灵活的脚本放置:异步脚本现在可以放置在组件树中的任何位置,而无需担心重复或重新定位。React 确保每个脚本只加载和执行一次,即使多个组件渲染它也是如此。</li>
<li>减少样板:您不再需要实现复杂的逻辑来管理脚本加载顺序或重复数据删除。React 会自动处理这些方面,从而简化您的代码。</li>
<li>提高代码可读性:通过将异步脚本放置在依赖它们的组件附近,您的代码变得更加直观且更易于维护</li>
</ul>
<p>在 HTML 中,普通脚本 (<script src="...">) 和延迟脚本 (<script defer="" src="...">) 按文档顺序加载,这使得在组件树深处渲染这些类型的脚本变得具有挑战性。然而,异步脚本 (<script async="" src="...">) 将按任意顺序加载。</p>
<p>在 React 19 中,我们提供了对异步脚本的更好支持,允许您在组件树中的任何位置(实际依赖脚本的组件内)渲染它们,而无需管理重新定位和重复数据删除脚本实例。</p>
<p>在所有渲染环境中,异步脚本将被去重,这样即使由多个不同的组件渲染,React 也只会加载并执行一次脚本。</p>
<p>在服务器端渲染中,异步脚本将包含在 <head> 中,并在绘制的更重要的资源之后再加载(例如样式表、字体和图像预加载)。</p>
<p>有关更多详细信息,请阅读 <script> 的文档。</p>
<pre><code class="language-jsx">
function MyComponent() {return (<div><script async={true} src="..." />Hello World</div>)
}function App() {<html><body><MyComponent>...<MyComponent> // won't lead to duplicate script in the DOM</body></html>
}</code></pre>
<h2 id="8-支持预加载资源">8. 支持预加载资源</h2>
<p>React 19 引入了一项重大的性能优化改进:内置支持预加载字体、脚本和样式表等资源。这允许您在用户与初始页面内容交互时主动在后台获取这些资源。</p>
<p>关键改进</p>
<ul>
<li>更快的页面加载:通过预加载资源,浏览器可以在渲染迫切需要它们之前获取它们,从而带来更流畅的用户体验和更快的感知加载时间。</li>
<li>改进的用户体验:预加载资源减少了初始页面加载后需要下载的内容量,从而为用户带来更无缝的体验,尤其是在连接速度较慢的情况下。</li>
<li>声明性控制:您可以通过 React 19 使用新的浏览器 API,如预加载、预取和预连接,从而在组件内提供对资源预加载的声明性控制。</li>
</ul>
<p>在初始文档加载和客户端更新期间,尽早告知浏览器可能需要加载的资源会对页面性能产生巨大影响。</p>
<p>React 19 包含许多用于加载和预加载浏览器资源的新 API,以便尽可能轻松地构建出色的体验,而不会因资源加载效率低下而受到阻碍。</p>
<pre><code class="language-jsx">
import { prefetchDNS, preconnect, preload, preinit } from 'react-dom'function MyComponent() {preinit('https://.../path/to/some/script.js', {as: 'script' }) // loads and executes this script eagerlypreload('https://.../path/to/font.woff', { as: 'font' }) // preloads this fontpreload('https://.../path/to/stylesheet.css', { as: 'style' }) // preloads this stylesheetprefetchDNS('https://...') // when you may not actually request anything from this hostpreconnect('https://...') // when you will request something but aren't sure what
}</code></pre>
<p>上述代码将生成以下 DOM/HTML:</p>
<pre><code class="language-html">
<html><head><!-- links/scripts 的优先级取决于它们在早期加载时的实用性,而不是调用顺序 --><link rel="prefetch-dns" href="https://..."><link rel="preconnect" href="https://..."><link rel="preload" as="font" href="https://.../path/to/font.woff"><link rel="preload" as="style" href="https://.../path/to/stylesheet.css"><script async="" src="https://.../path/to/some/script.js"></script></head><body>...</body>
</html></code></pre>
<p>这些 API 可用于优化初始页面加载,方法是将字体等其他资源的发现移出样式表加载。<br>
它们还可以通过预取预期导航使用的资源列表,然后在点击或悬停时热切地预加载这些资源,从而加快客户端更新速度。</p>
<p>有关更多详细信息,请参阅资源预加载 API。<br>
<a href="https://react.dev/reference/react-dom#resource-preloading-apis" target="_blank">https://react.dev/reference/react-dom#resource-preloading-apis</a></p>
<br/>
<br/>
<br/>
<h1 id="上一篇react-19新特性和更新介绍-02---服务器组件">上一篇:React 19新特性和更新介绍 02 - 服务器组件</h1>
<p><a href="https://www.cnblogs.com/eddyz/p/18724603" target="_blank">https://www.cnblogs.com/eddyz/p/18724603</a></p>
<br/>
<br/>
<br/>