2024年2月15日,由Joseph Savona,Ricky Hanlon,Andrew Clark,Matt Carroll和Dan Abramov撰写。
在React实验室的文章中,我们写有关正在进行中的研究和开发的项目。自从我们的上次更新以来,我们取得了显著的进展,我们想要分享我们的进展。
注意
React Conf 2024定于5月15日至16日在内华达州亨德森举行!如果您有兴趣亲自参加React Conf,您可以在2月28日之前注册抽奖。
有关门票、免费直播、赞助等更多信息,请参阅React Conf网站。
React编译器
React编译器不再是一个研究项目:该编译器现在已经在生产中为instagram.com提供动力,我们正在努力将该编译器推广到Meta的其他平台,并准备发布第一个开源版本。
正如我们在之前的文章中讨论的,当状态发生变化时,React有时会过度重新渲染。自React早期以来,我们针对这种情况的解决方案一直是手动记忆化。在我们当前的API中,这意味着应用useMemo
、useCallback
和memo
等API,手动调整React在状态更改时重新渲染的程度。但手动记忆化是一种妥协。它会使我们的代码变得混乱,容易出错,并且需要额外的工作来保持更新。
手动记忆化是一个合理的妥协,但我们并不满足。我们的愿景是,当状态更改时,React能够自动重新渲染UI的恰当部分,而不会妥协于React的核心思维模型。我们相信React的方法——将UI视为状态的简单函数,使用标准的JavaScript值和习惯用法——是React之所以对许多开发人员易于接近的关键部分。这就是为什么我们投资于构建React的优化编译器的原因。
JavaScript是一种因其松散规则和动态性而难以优化的语言。React编译器能够通过对JavaScript的规则和“React规则”建模来安全地编译代码。例如,React组件必须是幂等的——在给定相同输入的情况下返回相同的值——并且不能突变props或状态值。这些规则限制了开发人员可以做什么,并有助于为编译器提供优化的安全空间。
当然,我们明白开发人员有时会打破规则,我们的目标是使React编译器在尽可能多的代码上即插即用。编译器试图检测代码何时不严格遵循React的规则,并且将在安全的情况下编译代码,如果不安全则跳过编译。我们正在针对Meta庞大而多样的代码库进行测试,以帮助验证这种方法。
对于那些想确保其代码遵循React规则的开发人员,我们建议启用Strict Mode和配置React的ESLint插件。这些工具可以帮助捕捉React代码中的微妙错误,提高应用程序的质量,并为即将推出的功能(如React编译器)未来提供支持。我们还正在制作关于React规则的综合文档,以及更新我们的ESLint插件,以帮助团队理解并应用这些规则,以创建更强大的应用程序。
要查看编译器的实际效果,您可以查看我们去年秋季的演讲。在演讲时,我们在instagram.com的一个页面上尝试了React编译器的早期实验数据。自那时以来,我们已经将编译器推广到了instagram.com的生产环境。我们还扩大了团队,以加速在Meta的其他平台上推出和开源编译器。我们对未来的道路感到兴奋,并将在未来几个月内分享更多信息。
Actions
我们之前分享过我们正在研究使用Server Actions从客户端发送数据到服务器的解决方案,以便执行数据库突变和实现表单。在Server Actions的开发过程中,我们扩展了这些API以支持在仅客户端应用程序中处理数据。
我们将这一更广泛的功能集合简称为“Actions”。Actions允许您将函数传递给DOM元素,例如<form/>
:
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</form>
action
函数可以同步或异步操作。您可以在客户端使用标准JavaScript定义它们,或者在服务器上使用'use server'
指令。在使用Action时,React将为您管理数据提交的生命周期,提供像useFormStatus
和useFormState
这样的钩子,以访问表单操作的当前状态和响应。
默认情况下,Actions在过渡内提交,使当前页面在操作处理期间保持交互。由于Actions支持异步函数,我们还添加了在过渡中使用async/await
的功能。这允许您在像fetch
这样的异步请求开始时通过过渡的isPending
状态显示待处理的UI,并在应用更新的整个过程中显示待处理的UI。
除了Actions,我们还引入了一个名为useOptimistic
的功能,用于管理乐观状态更新。使用此钩子,您可以在客户端上乐观地设置数据的最终状态,假设提交成功,并恢复到从服务器接收的数据的值。它使用常规的async
/await
,因此无论您是在客户端上使用fetch
还是在服务器上使用Server Action,它都可以正常工作。
库作者可以使用useTransition
在自己的组件中实现自定义的action={fn}
属性。我们的目标是当设计其组件API时,库采用Actions模式,为React开发人员提供一致的体验。例如,如果您的库提供了一个<Calendar onSelect={eventHandler}>
组件,请考虑还提供一个<Calendar selectAction={action}>
API。
虽然我们最初关注了用于客户端-服务器数据传输的Server Actions,但我们对React的理念是在所有平台和环境中提供相同的编程模型。如果可能的话,如果我们在客户端引入一个功能,我们也会让它在服务器上工作,反之亦然。这一理念使我们能够创建一套API,无论应用程序在何处运行,都能正常工作,从而更容易升级到不同的环境。
Actions现在在Canary频道中可用,并将在React的下一个版本中发布。
React Canary的新功能
我们引入了React Canaries作为在它们的设计接近最终之前采用单个新稳定功能的选项,而不是在稳定的semver版本中发布它们之前。
Canaries改变了我们开发React的方式。以前,功能会在Meta内部进行私下研究和构建,因此用户只会在发布到Stable时看到最终成品。有了Canaries,我们正在与社区的帮助下公开构建这些功能,以完成我们在React实验室博客系列中分享的功能。这意味着您可以更早地了解新功能,因为它们在最终完成之前就已经接近完成。
React Server Components、Asset Loading、Document Metadata和Actions都已经加入了React Canary,并且我们在react.dev上为这些功能添加了文档:
指令:
"use client"
和"use server"
是为全栈React框架设计的打包器功能。它们标记了两个环境之间的“分割点”:“use client”指示打包器生成一个<script>
标签(类似于Astro Islands),而“use server”告诉打包器生成一个POST端点(类似于tRPC Mutations)。它们一起允许您编写可重用的组件,将客户端交互性与相关的服务器逻辑组合起来。文档元数据: 我们为渲染
<title>
、<meta>
和元数据<link>
标签提供了内置支持,可以在组件树的任何地方使用。这在所有环境中都以相同的方式工作,包括完全客户端端代码、SSR和RSC。这为像React Helmet这样的库先驱的功能提供了内置支持。资产加载: 我们将Suspense与样式表、字体和脚本等资源的加载生命周期集成在一起,以便React考虑它们来确定元素(如
<style>
、<link>
和<script>
)的内容是否准备好显示。我们还添加了新的资源加载API,如preload
和preinit
,以在何时加载和初始化资源方面提供更大的控制。操作: 如上所述,我们添加了Actions来管理从客户端发送数据到服务器的操作。您可以将
action
添加到元素,如<form/>
,使用useFormStatus
访问状态,使用useFormState
处理结果,并使用useOptimistic
乐观地更新UI。
由于所有这些功能都共同工作,单独在Stable频道中发布它们是困难的。在没有配套的访问表单状态的情况下发布Actions将限制Actions的实际可用性。在没有集成Server Actions的情况下引入React Server Components将复杂化在服务器上修改数据的过程。
在我们可以将一组功能发布到Stable频道之前,我们需要确保它们可以协同工作,并且开发人员拥有在生产环境中使用它们所需的一切。React Canaries允许我们逐个开发这些功能,并逐步发布稳定的API,直到整个功能集完成。
React Canary中当前的功能集已经完成并准备好发布。
React的下一个主要版本
在经过几年的迭代后,react@canary
现在已经准备好切换到react@latest
。上述新功能与您的应用程序运行的任何环境兼容,为生产使用提供了一切所需。由于资产加载和文档元数据对一些应用程序可能是破坏性的更改,下一个React版本将是一个主要版本:React 19。
为了准备发布,我们仍然有很多工作要做。在React 19中,我们还将添加一些长期要求的改进,这些改进需要破坏性变更,例如对Web组件的支持。我们现在的重点是完成这些变更,为发布做好准备,为新功能准备文档,并发布包含的公告。
在接下来的几个月里,我们将分享有关React 19包含的所有信息,如何采用新的客户端功能以及如何为React Server Components构建支持。
Offscreen(更名为Activity)
自上次更新以来,我们将正在研究的功能从“Offscreen”更名为“Activity”。名称“Offscreen”暗示它仅适用于应用程序中不可见的部分,但在研究该功能时,我们意识到应用程序的某些部分可能是可见但不活动的,例如模态框后面的内容。新名称更贴切地反映了标记应用程序的某些部分为“活动”或“非活动”的行为。
Activity仍在研究中,我们剩下的工作是最终确定向库开发人员公开的基本组件。在我们专注于发布更完整的功能之际,我们已将此区域放在了次要位置。
除了此更新外,我们的团队还在会议上发表演讲,并出现在播客中,以更详细地介绍我们的工作并回答问题。
Sathya Gunasekaran在React India会议上介绍了React编译器
Dan Abramov在RemixConf上发表了一场名为“React from Another Dimension”的演讲,探讨了React Server Components和Actions可能如何创建的替代历史
Dan Abramov在Changelog的JS Party播客上接受了关于React Server Components的采访
Matt Carroll在Front-End Fire播客上接受了采访,他在那里讨论了The Two Reacts
感谢Lauren Tan,Sophie Alpert,Jason Bonta,Eli White和Sathya Gunasekaran对本文的审阅。
感谢阅读,并期待在React Conf见!