首页 > web前端 > js教程 > React 更新笔记伴侣

React 更新笔记伴侣

Linda Hamilton
发布: 2025-01-12 16:39:44
原创
935 人浏览过

React Update Notes Companion

React 新主要版本的更新说明总是信息密集得令人难以置信,而且框架本身非常广泛,我总是发现自己在做笔记并与参考文档进行比较,以尝试不仅仅是弄清楚发生了什么变化以及如何使用它,以及更新说明中谈到的各种主要概念实际上是如何在幕后工作的。 虽然 React 的文档非常齐全,但更新说明并不总是“足以”理解这些概念 - 例如,在 React 19 更新说明中,我发现 useOptimistic 的示例令人困惑,而且实际上对于钩子的实际工作原理有点不准确。

我决定把我在回顾 React 19 变化时所做的笔记写下来,作为那些一直害怕梳理笔记并弄清楚它们的含义的人的伴侣 - 所以让我们开始吧。

操作和表单处理/useActionState

第一个重大改进是表单处理的巨大改进。 React 已逐渐致力于消除样板文件并更好地与原生 HTML 表单集成,其新的 useActionState 就是这一推动的一部分。它旨在帮助改进错误处理(因为它现在是内置的),它会自动跟踪加载状态,以便您不必不断在挂起状态下手动编码,并改进了对渐进增强的支持。

现在,我发现为 useActionState 提供的代码示例非常混乱,事实上这个代码示例是我开始写这篇文章的全部原因 - 事实上,useActionState 有两个部分,它们组合在例如为了节省空间,但最终大大降低了清晰度。 useActionState 返回一个元组,用于跟踪表单提交中的异步操作何时完成,而您传递的操作的修改版本将直接传递到表单。 useActionState 本身需要两个输入 - 异步 formAction(调用时接收先前状态和表单数据作为参数)和初始状态 - 可以为 null、零或变量。

如果您的表单尚未提交,则之前的状态是initialState。如果表单之前已经提交过,那么它就是提交的任何内容 - 在服务器功能中,您实际上可以在水合发生之前显示服务器响应。 useActionState 最后可以接受带有表单要修改的唯一页面 URL 的字符串。 换句话说,它还可以接受可选的永久链接参数,这对于渐进式增强特别有用 - 如果用户在 JavaScript 加载之前提交表单,它会告诉浏览器导航到哪里。

最后,useActionState返回的元组是一个数组,其中包含当前状态(在初始渲染期间它是您的initialState值),您可以将react修改的formAction作为action传递给表单或将按钮作为prop传递给,和一个 isPending 标志/状态变量。我很期待看到 React 团队还会推出哪些其他新开发成果,因为这个似乎特别有用。

React-DOM 更新

<表格>行动

任何使用过 NextJS 和表单操作的人都会熟悉这个 React-dom 添加,而且 Reac 团队似乎已经决定表单操作已经准备好迎接黄金时段了。对于没有在 NextJS 或 React 之上的其他框架中使用过它们的人来说,它们基本上是一种通过使用本机表单提交来增强 React 性能的方法。 您可以通过 action 属性传递本机表单提交,而不是 onClick - 传递给 action 或 formAction 的任何函数都将自动处理其提交。 React 还会自动重置任何不受控制的表单字段。您还可以通过 API 手动选择重置它。 React 团队还将错误处理与错误边界集成在一起。 我不会谈论太多,因为我假设大多数人都记得 NextJS 中的它们,但如果有人有疑问,我可以写一篇后续文章。

useFormStatus 钩子

这是一个很好的补充,可以帮助您了解表单中发生的情况,而无需使用道具钻探或使用上下文 - 如果您问为什么不使用道具钻探,它与保持代码可维护且易于修改有关。 至于上下文,过度使用上下文将导致性能问题,因为每当上下文中的某些内容发生变化时,订阅特定上下文的每个组件都会重新呈现。 因此,它可以整理代码,减少出错的机会,并防止您影响应用程序的性能。

该钩子返回一个具有四个属性的对象:pending - 一个布尔值,表示是否有待处理的提交,data - 一个包含父表单提交的数据的 formData 对象(如果没有活动提交或父表单,则为 null )、方法(get 或 post)和操作 - 这是通过 action 属性传递的操作。

使用乐观钩子

管理乐观更新的更简单的新方法。 如果您不熟悉乐观更新,这意味着在服务器端更新发生之前更新客户端显示。 如果您曾经喜欢过某件事,看过动画播放并将其在屏幕上注册为喜欢,然后收到一条提示“喜欢失败”的 toast 错误,这是由于乐观渲染造成的。

useOptimistic 钩子接受一个你想要乐观渲染的有状态变量和一个更新函数,它必须是一个纯函数 - 换句话说,一个没有副作用的确定性函数。基本上,更新函数检索状态更新的来源 - 通常类似于 formData.get(‘name’)。 useOptimistic 然后返回两个值:乐观状态和 addOptimistic 函数。

我发现这方面的文档有点薄弱,特别是在使用流程方面 - 基本上,您调用 useOptimistic 并将其传递给您想要显示乐观更新的初始状态和更新函数。您会收到两个函数 - 新的乐观增强状态值 (optimisticState) 和一个乐观地更改状态的函数。当用户提交新值时,您可以调用第二个函数(在文档中称为 addOptimistic),并将用户提交的值传递给它。在您的组件中,每当您想要乐观地呈现有状态变量时,您都可以将乐观增强的有状态值传递给它。

总的来说,我真的很喜欢这种更标准化的执行乐观更新的方式 - 我之前在 NextJS 中缓存和进行乐观更新时遇到过问题,所以创建乐观更新的标准化方法很棒,我相信这会冒泡到 NextJS(如果还没有)。

使用API​​

这是一个超级密集的 API,它是一种在 React 渲染页面时访问资源的全新方式 - 使用的确切措辞是“在渲染中读取资源”。那么它具体是做什么用的呢? 这个新的 API 可用于访问条件或循环内部的组件信息。 如果您不熟悉为什么它有用,它与 React 的渲染过程的工作原理有关。 React/React-Fiber 依赖于每次都以相同的顺序渲染所有内容,这就是为什么在渲染过程中通常无法访问大多数钩子的原因。 更清楚地说,状态实际上是根据调用钩子的顺序来跟踪的,因此如果以不可预测的顺序调用钩子,最终会出现渲染错误。一个很好的例子是根据用户是否登录来访问主题上下文。

那么为什么这是一个重要的发展呢? 这意味着您只能在实际需要时加载信息/数据,例如仅当用户实际登录时,您才会加载特殊主题的 css。数据必须是可序列化的,因此这意味着您可以将承诺从服务器组件发送到客户端组件,而实际上它已经在运行中 - 这意味着瀑布请求更少,并且它们会自动并行放置。 值得注意的是,在服务器组件中工作时,您实际上应该更喜欢使用 async/await 而不是用于数据获取 - 这是因为 async/await 将从其停止的位置恢复渲染,而使用将触发完全重新渲染数据解析后的组件。当然,我还想指出,这个变化实际上也意味着,如果你配置使用不正确,你就有了一个新的潜在的瀑布请求源。

需要注意的一件非常重要的事情是,您不能在 try/catch 块中使用“use”API - 这是因为“use”在使用 Promise 调用时会自动使用 React Suspense 边界。 try/catch 块会阻止您达到 React 级别,因为任何错误实际上都会在您达到 React 之前停止 JS 级别的执行,从而破坏功能。 与其他钩子一样,它们必须位于特定组件或函数范围的顶层(同样,由于渲染顺序)。

所以,“使用”的真正目的是帮助您访问上下文以有条件地渲染事物,并且仅在实际需要时才获取数据。这是让 React 不再那么晦涩难懂、简化条件数据获取、改善开发体验并一次性提高性能的又一步。它需要更有经验的 React 开发人员重新学习如何做主题之类的事情,但我认为这使得新用户更容易使用该框架,这总是很棒的。

新的 React Dom 静态 API

这两个新的静态 API prerender 和 prerenderToNodeStream 都是对 renderToString 的改进,renderToString 用于服务器端渲染 (SSR)。这些新的改进是为了使用 renderToString 进行静态站点生成 (SSG)。 与可以在内容块可用时发送内容块的传统流式 SSR 不同,这些新 API 专门等待所有数据加载,然后再生成最终 HTML。它们旨在与 Node.js Streams 和 Web Streams 等现代流式环境无缝协作,但它们故意不支持流式传输部分内容 - 相反,它们确保您在构建时获得完整、完全加载的页面。它们与传统的流式 SSR 方法不同,传统的流式 SSR 方法会在数据可用时发送预渲染站点。

我们已经在 React 之上构建了支持 SSG 的框架,例如 NextJS,但这旨在成为 React 针对 SSG 的本机功能。拥有 SSG 的框架使用 renderToString,然后围绕它构建自己的复杂数据获取协调。 这对于用户自己创建来说非常困难,并且这些框架使用极其复杂的管道来做到这一点。 这些新方法本质上是允许在静态 HTML 生成期间加载数据,如果您不熟悉 SSG,它本质上是在构建时渲染所有内容,并且无疑是渲染页面的最快方法,因为它没有根据用户请求呈现页面,因此对于那些不想使用 Next 之类的功能的人来说,拥有这种功能非常棒,因为 Next 要么需要在 Vercel 上部署,要么需要极其复杂的部署过程。

服务器组件

React 服务器组件的概念对于使用过 NextJS 最新版本的人来说并不陌生,但对于没有使用过的人来说,服务器组件是一种围绕数据获取的新范例。坦率地说,服务器组件(和服务器操作)的概念本身就值得写一整篇文章,但简单地总结一下这个概念,服务器组件始终在发送到客户端之前在服务器上呈现,即使在加载 javascript 之后也是如此。 这意味着后续渲染是在服务器端完成的。

这些组件的主要优点是安全性和数据获取:如果您在服务器组件内请求数据,请求信息永远不会显示在客户端,只会显示响应,从而更加安全。 API、端点等根本无法在客户端访问。它还减少了包的大小,因为所述操作的 JavaScript 永远不会发送到客户端。它还允许您在服务器上执行内存或计算密集型操作,以减轻功能较弱的计算机上的渲染负担。 它们还减少了客户端瀑布,因为可以在靠近数据库的计算机上执行顺序数据获取,但当然它也开辟了全新服务器端瀑布的可能性,因为您的开发人员无法访问来自测试浏览器开发人员的简单请求信息工具,并且必须使用 OpenTelemetry 收集器和查看器之类的东西来检查它们。最后,服务器组件也非常适合渐进增强。

服务器组件也有一系列限制:你不能使用本地浏览器 API(本地存储、窗口等),React hooks 的工作方式会有所不同,你不能依赖或使用状态,并且你可以'不使用事件处理程序,因此组件的用户交互性明显很小。 基本上,将此范例视为服务器组件中的数据获取和客户端组件上的交互。

对于任何刚接触服务器组件的人来说,最重要的警告是您不能将它们导入客户端组件 - 如果您这样做,这将出错(假设您已经添加了一些数据获取),因为它会导致编译器处理所述服务器组件作为客户端组件。如果要将服务器组件传递给客户端组件,则需要通过 {children} 属性传递它。

服务器操作

这是另一个复杂的主题,对您如何构建产品和功能有很多影响,这些也已经在 NextJS 中出现了一年左右。 服务器操作是通过在文件顶部键入“use server”来声明的,并传递对所述服务器函数的直接引用,然后可以从客户端组件内部调用该函数。

在某种程度上,它们在概念上类似于远程过程调用(RPC) - 它们都允许您从客户端调用服务器端函数,都抽象了客户端-服务器交互的复杂性,并且都处理序列化和反序列化,但是有一些关键差异需要注意。 服务器操作的主要好处是它们可以与 React 的渐进增强配合使用,帮助跨客户端/服务器边界强制执行类型安全,具有内置的性能优化(与渐进增强相关),并且与 React 生态系统有更无缝的集成因为它们提供内置的待处理状态,并自动与本机表单提交集成。

当您谈论现代 RPC(例如 gRPC)时,它已经具有类型安全性和一些性能优化,服务器操作的主要优势通常可以归结为内置表单处理和渐进增强,但重要的是它也有效具有反应悬念和错误边界。最重要的是,部署要简单得多,因为您不一定需要为 gRPC 设置单独的服务器,因此这些对于较小的项目来说绝对更理想,尽管当涉及到较大的项目时,我可以看到 gRPC 更可取,因为它在后端语言等方面为您提供了更大的灵活性

作为提供者的上下文

这本质上是语法的简化,帮助 React 拥有更清晰的声明性语法。 说实话,除了“我喜欢”之外,我没什么可说的。

Ref 作为 Prop 和 Ref 的清理函数

以前,要清理引用,您必须在组件内部执行空检查,并且引用将在某种程度上不确定的时间被清理。当组件卸载时,React 会使用 null 调用您的 ref 回调,要求您显式处理附加和分离情况。新 ref 语法的优点是确定性清理 - 这意味着现在使用外部资源和第三方库更加容易,因为您将确切地知道何时发生 ref 清理(卸载时)。 使用新方法,您可以直接返回清理函数。 TypeScript 集成需要显式返回语句,以避免清理函数出现歧义。

我真的很喜欢这种实现方式,因为它与 useEffect 的模式相同 - 保持整个框架的一致性非常棒。我认为这个新的引用清理对于 WebGL 上下文和其他大量资源非常有用,而且对于处理使用本机 JS 方法添加的 DOM 事件侦听器也非常有用。 这是因为以前,react 会在清理时删除对 dom 元素的引用…但是如果你这样做了,删除事件监听器就会变得更加复杂,因为你已经丢失了对它们所附加的组件的引用。 因此,您必须将引用存储在元素之外,从而增加了一层复杂性。现在,您可以删除组件返回函数内的事件侦听器,因为您保留对所述返回函数内的 ref 的访问权限。这也意味着我们在大多数情况下不再需要担心 null 情况,因为在使用清理函数时,React 不会再使用 null 来调用 ref。清理函数本身取代了该功能,使我们的代码更干净、更可预测。

useDeferredValue

useDeferredValue 挂钩的目的是管理计算量大的操作,同时维护响应式用户界面。它通过允许组件在后台计算或获取新数据时显示先前的“陈旧”值来实现此目的。一个常见的用例是搜索功能,它会在用户键入时显示结果 - 如果没有延迟,每次击键都可能触发昂贵的搜索操作,从而使输入感觉缓慢。使用 useDeferredValue,界面可以通过显示以前的搜索结果同时计算新的搜索结果来保持响应。

这个新添加是对该钩子初始加载行为的重要改进。以前,第一次渲染将立即使用传递给 useDeferredValue 的任何值,这可能会在开始时触发昂贵的计算。新版本允许您提供立即显示的轻量级初始值(例如空字符串),同时在后台处理更昂贵的值。这意味着您可以向用户显示安全默认值的即时反馈,然后在昂贵的计算完成后使用真实数据更新它。从本质上讲,这使得 useDeferredValue 能够更好地提高性能。

文档元数据添加

这些新的更改是为了在实际组件内添加各种元数据标签。他们会讨论三个选项:

和 <meta>。 值得注意的是,<title>没有重复数据删除 - 每个存储库您只打算使用它一次。另外两个,<link>和<meta>,在重复数据删除方面有一些相当复杂的交互,在学习之后,我认为这些交互对于 90% 的用户来说并不是特别相关。 <p>这些更改的主要好处是它们允许组件真正独立:它们现在可以管理自己的元数据以及样式和脚本。您不再需要弄清楚如何将元数据提升到顶层或使用库来完成此操作,这使得 SEO 变得更容易。 SPA 中的不同页面可以更轻松地拥有不同的元数据,而不会冒元数据与页面上显示的内容不同步的风险,而这以前是不同页面拥有不同元数据时存在的风险。</p> <p><strong>样式表支持</strong></p> <p>人们可能已经使用 tailwind 太久了,以至于他们已经忘记了,但是运行非封装的 CSS 可能会由于样式表的加载方式(即加载顺序优先规则)而产生问题。首先,您最终可能会看到闪烁的无样式内容 - 任何时候在 CSS 下载完成之前加载和呈现 HTML 时,它都会显示为完全白色的页面,通常在具有大量字体大小和本机图像大小的单列中,这通常使其无法读取。</p> <p>此外,CSS 加载顺序规则可能会产生其他问题:例如,如果您有具有相同特异性的规则,但希望它们按特定顺序加载。例如,当您有不同的主题选项(例如深色模式)时,这是相关的。如果深色模式 CSS 打算最后加载,但深色模式的 CSS 文件首先加载,则最终可能会出现深色模式为浅色,或者应用程序的某些部分遵守规则而其他部分不遵守规则的情况。 t 坚持。 </p> <p>有很多解决方案可以避免这种情况,比如 JS 中的 CSS,将所有 CSS 加载到 </p> 中。然而,这些新的 CSS 更改旨在通过以声明方式设置优先级来帮助管理这些问题 - 它还确保放置在组件中的任何样式表在组件本身呈现之前加载。 它还内置了重复数据删除功能,因此当您重用包含样式表链接的组件时,您不会最终多次加载相同的样式表。 <p>访问这个新功能的方式(在渲染组件之前等待 css 加载、自动将 CSS 提升到头部等)也非常简单 - 您只需要在特定的 <link> 中包含优先级;成分。 总的来说,我是打字稿的爱好者,所以它并不能完全解决我的任何特定问题,但我确信这将是非常有用的大型遗留项目。 </p> <p><strong>异步脚本支持</strong></p> <p>这解决了一个边缘情况,而不是创建一个新的核心功能让人们担心 - 使用 <script> 手动添加/直接管理脚本根据我的经验,标签在现代 React 中非常罕见。 大多数开发人员都使用 webpack 或 vite 等捆绑器、包管理器、导入语句,如果需要动态加载脚本,他们会使用 useEffect 之类的东西。 然而,这与 SSR 和更好的 UX 相关,以避免上述 <head> 中内容加载顺序的问题。 </script></p> <p>由于脚本可以异步加载,这意味着在没有正确样式的情况下加载 React 应用程序的可能性会大大降低。 这一变化也与管理需要直接脚本标签的遗留系统的开发人员或负责管理无法捆绑的第三方脚本(例如分析、小部件等)或防止特别繁重的脚本(例如视频)的开发人员相关。播放器)在有必要提高性能之前加载,但由于我没有这些经验,所以我无法真正评论更多。 </p> <p><strong>支持预加载资源</strong></p> <p>用于管理资源预加载的新 API 非常有趣,特别是对于必须确保网络条件千差万别的全球受众获得无缝加载体验的大型企业,以及依赖不同来源的大量第三方资源的内容密集型应用程序,对于任何感知性能对用户保留很重要的应用程序(说实话,这几乎就是一切)</p> <p>然而,大多数基于 React 的框架(例如 Next、Remix 等)往往已经管理了这一点 - 我不太确定这些新的 API 将如何与所述框架交互,但似乎是这样。将成为新的冲突来源,也是使用这些框架并尝试使用这些新 API 优化性能时需要牢记的重要事项。 </p> <p>虽然预加载绝对是具有最广泛用例(加载样式表等)的 API,但由于上述问题,我认为最相关的是 preinit - 这是一种立即启动的硬加载,旨在急切加载脚本。 我能想到的最明显的用途是立即在购物车评论中加载条纹 - 这应该会显着加快结帐过程,这是电子商务的一个步骤,您绝对不想因为性能问题而失去客户。 </p> <p><strong>第三方脚本兼容性</strong></p> <p>考虑到浏览器插件越来越常见,这是一个非常受欢迎的变化 - 我能想到的一些修改 DOM 结构的例子可能会从这一变化中受益,包括广告拦截器、价格比较工具、语法/AI 助手插件和翻译扩展。在没有实际阅读水合现在如何工作的情况下,对此没有太多可说的,尽管主要的变化似乎是编译器跳过了意外的标签。 </p> <p><strong>更好的错误报告</strong></p> <p>我发现这一部分非常不言自明。 错误处理的变化总是受欢迎的——以前存在的错误垃圾邮件总是让追踪特定错误变得有点困难。如果您使用一些维护不太好的第三方解决方案,这些解决方案往往会引发大量错误,这一点尤其重要。<br> 支持自定义元素</p> <p>这部分对我来说特别有趣,因为我以前从未听说过自定义元素。 简而言之,自定义元素是一种新的 Web 标准,可让开发人员创建自己的 HTML 元素。 由于遵循上述 Web 标准,它们旨在在任何页面上运行并且与框架无关 - 例如,您可以编写一个在所有个人项目中常用的组件(您倾向于以 svelte 的方式进行操作),然后将其用于较小的项目您为初创公司所做的合同工作或 vue 中的短期合同等</p> <p>React 用于将无法识别的 props 视为属性而不是实际属性 - 新的更新添加了一个允许正确使用 props 来创建自定义元素的系统。看来通过此更改,现在完全支持在 React 中使用自定义元素。 顺便说一句,除了 props 问题之外,React 的合成事件系统过去也存在不兼容性(现已解决)——自定义元素无法与系统完全集成,因此在某些情况下您实际上必须手动添加带有 ref 的事件侦听器以及其他解决方法。 </p>

以上是React 更新笔记伴侣的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板