关于 React19,你需要了解的前因后果

大家好,我卡颂。

React当前的稳定版本是18.2,发布时间是22年6月,在此之后就没有新的稳定版本发布。

直到今年2月15日,官方博客才透露下一个稳定版本的计划。没错,他就是React19

为什么时隔1年多才公布下个稳定版本的计划?

为什么下个版本直接跳到了19?

18我都还没升呢,19就来了,是不是要学很多东西?

这篇文章会为你详细解答这些疑问。

打包领取卡颂原创React教程、加入人类高质量前端群

从React16聊起

近年来React最为人津津乐道的版本应该是16.8,这个版本引入了Hooks,为React(乃至整个前端框架领域)注入了新的活力。

再之后的v17没有新特性引入。既然没有新特性引入,为什么要发布一个大版本(从16到17)呢?

这是因为从同步更新 升级到并发更新React,中间存在breaking change

这么大体量的框架,在升级时需要保证过程尽可能平顺。这除了是一种专业、负责的体现,更重要的,版本割裂会造成大量用户损失(参考当年ng1升级到anuglar2时)。

当升级到18后,React团队发现 ------ 真正升级到18,并大量使用并发特性(比如useTransition)的开发者并不多。

更常见的场景是 ------ 知名开源库集成并发特性,开发者再直接用这些库。

所以,React团队转变策略,将迭代重心从赋能开发者 转变为赋能开源库。那么,什么样的库受众最多呢?显然是框架。

所以,React的重心逐渐变为 ------ 赋能上层框架,开发者通过使用上层框架间接使用React

为什么我说React团队转变了策略,而不是React团队一开始的计划就是赋能上层框架呢?

如果一开始的计划就是赋能上层框架React团队就不会花大量精力在版本的渐进升级上 ------ 反正开发者最终使用的会是上层框架(而不是React),版本割裂上层框架会解决,根本不需要引导开发者升级React

策略改变造成的影响

策略转变造成的影响是深远且广泛的,这也是为什么18.2后一年多都没有新的稳定版本出现。

最基本的影响是 ------ 特性的迭代流程变了。

React诞生的初衷是为了解决Meta内部复杂的前端应用,所以React之前的特性迭代流程是:

  1. 新特性开发完成

  2. 新特性在React内部产品试用,并最终达到稳定状态

  3. 开源供广大开发者使用

但随着策略转变为赋能上层框架 ,势必需要与主流上层框架团队(主要是Next.js)密切合作。

如果按照原来的迭代流程,上层框架团队属于Meta之外的第三方团队,只能等新特性开源后才能使用,这种合作模式显然太低效了。

于是,React团队提出了一个新的特性发布渠道 ------ canary,即:新特性开发完成后,可以先打一个canary版本的React供外部试用,等特性稳定后再考虑将其加入稳定版本中。

可能有些存在于canary中的特性永远不会出现在稳定版本的React中,但不妨碍一些开源库锁死canary版本的React,进而使用这些特性。

那么,为什么时隔1年多才公布下个稳定版本的计划?主要有4个原因。

原因1:新特性主要服务于Next,没必要出现在稳定版本中

策略改变除了影响特性的迭代流程 ,还让React团队成员陷入一个两难的境地 ------ 我该优先服务上层框架还是Meta

我们可以发现,在之前的迭代流程中,一切都围绕Meta自身需求展开。React团队成员作为Meta员工,这个迭代流程再自然不过。

但是,新的迭代流程需要密切与Next团队合作,那么问题来了 ------ 作为Meta员工,新特性应该优先考虑Next的需求还是Meta的需求?

为了完成赋能上层框架 的任务,显然应该更多考虑Next的需求。我们能看到一些React团队成员最终跳槽到Vercel,进入Next团队。

所以,在此期间产出的特性(比如server actionuseFormStatususeFormState)更多是服务于Next,而不是React

如果基于这些特性发布新的稳定版本,那不用Next的开发者用不到这些特性,用Next的开发者依赖的是canary React,所以此时升级稳定版本是没意义的。

原因2:新特性必须满足各种场景,交付难度大

Nextweb框架,围绕他创造的新React特性只用考虑web这一场景。

React自身的定位是宿主环境无关的UI库,还有大量开发者在非web的环境使用React(比如React Native),所以这些特性要出现在稳定版本的React中,必须保证他能适配所有环境。

举个例子,Server Actions这一特性,用于简化客户端与服务器数据发送的流程 ,当前主要应用于NextApp Router模式中。

比如下面代码中的MyForm组件,当表单提交后,serverAction函数的逻辑会在服务端执行,这样就能方便的进行IO操作(比如操作数据库):

js 复制代码
// 服务端代码

async function serverAction(event) {
  'use server'
  // 在这里处理服务端逻辑,比如数据库操作读写等
}

function MyForm() {
  return (
    <form action={serverAction}>
      <input name="query" />
      <button type="submit">Search</button>
    </form>
  );
}

App Router的场景主要是RSC(React Server Component),除了RSC外,SSR场景下是不是也有表单?不使用服务端相关功能,单纯使用React进行客户端渲染,是不是也有表单的场景?

所以,Server Actions特性后来改名为Actions,因为不止Server场景,其他场景也要支持Actions

比如下面代码中,在客户端渲染的场景使用Actions特性:

js 复制代码
// 前端代码

const search = async (event) => {
  event.preventDefault();
  const formData = new FormData(event.target);
  const query = formData.get('query');

  // 使用 fetch 或其他方式发送数据
  const response = await fetch('/search', /*省略*/);

  // ...处理响应
};

function MyForm() {
  return (
    <form action={search}>
      <input name="query" />
      <button type="submit">Search</button>
    </form>
  );
}

你以为这就完了?还早。form组件支持Actions,那开发者自定义的组件能不能支持Actions这种前、后端交互模式

比如下面的Calendar组件,之前通过onSelect事件响应交互:

html 复制代码
<Calendar onSelect={eventHandler}>

以后能不能用Actions的模式响应交互:

html 复制代码
<Calendar selectAction={action}>

如何将平平无奇的交互变成Actions交互呢?React团队给出的答案是 ------ 用useTransition包裹。所以,这后面又涉及到useTransition功能的修改。

Actions只是一个例子,可以发现,虽然新特性是以web为始,但为了出现在稳定版本中,需要以覆盖全场景为终,自然提高了交付难度。

原因3:老特性需要兼容的场景越来越多,工作量很大

新特性越来越多,老特性为了兼容这些新特性也必须作出修改,这需要大量的时间开发、测试。

举两个例子,Suspense在v16.6就引入了,它允许组件"等待"某些内容变得可用,并在此期间显示一个加载指示器(或其他后备内容)

Suspense最初只支持懒加载组件(React.lazy)这一场景。随着React新特性不断涌现,Suspense又相继兼容了如下场景:

  • Actions提交后的等待场景

  • 并发更新的等待场景

  • Selective Hydration的加载场景

  • RSC流式传输的等待场景

  • 任何data fetching场景

为了兼容这些场景,Suspense的代码量已经非常恐怖了,但开发者对此是无感知的。

再举个和SuspenseuseEffect这两个特性相关的例子。

Suspense为什么能在中间状态完成状态 之间切换?是因为在Suspense的源码中,他的内部存在一个Offscreen组件,用于完成两颗子Fiber树的切换。

React团队希望将Offscreen组件抽离成一个单独的新特性(新名字叫Activity组件),起到类似VueKeep-Alive组件的作用。

Activity组件既然能让组件显/隐,那势必会影响组件的useEffect的触发时机。毕竟,如果一个组件隐藏了,但他的useEffect create函数触发了,会是一件很奇怪的事情。

所以,为了落地Activity组件,useEffect的触发逻辑又会变得更复杂。

原因4:特性必须形成体系才能交付

虽然这一年React团队开发了很多特性,但很多特性无法单独交付,必须构成一个体系后再统一交付。

比如刚才提到的useFormStatususeFormState是服务于Actions特性的,Actions又是由Server Actions演化而来的,Server Actions又是RSC(React服务端组件)体系下的特性。

单独将useFormStatus发布在稳定版本中是没意义的,他属于RSC体系下的一环。

所以,即使新特性已经准备就绪,他所在的体系还没准备好的话,那体系下的所有特性都不能在稳定版本中交付。

总结

为什么时隔1年多才公布下个稳定版本的计划?主要是4个原因:

  1. 新特性主要服务于Next,没必要出现在稳定版本中

  2. 新特性必须满足各种场景,交付难度大

  3. 老特性需要兼容的场景越来越多,工作量很大

  4. 特性必须形成体系才能交付

那为什么下个稳定版本不是v18.x而是v19呢?这是因为部分新特性(主要是Asset LoadingDocument Metadata这两类特性)对于一些应用会产生breaking change,所以需要发一个大版本。

从上述4个原因中的第四点可以知道,既然有v19的消息,势必是因为已经有成体系的新特性可以交付,那是不是意味着要学很多东西呢?

这一点倒不用担心,如果你不用Next,那你大概率不会接触到RSC,既然不会接触RSC,那么RSC体系下的新特性你都不会用到。

v19对你最大的影响可能就是新特性对老API的影响了,比如:

  • useContext变为use(promise)

  • Activity组件使useEffect的触发时机更复杂(应该不会在v19的第一个版本中)

这些的学习成本都不大。

关于v19的进一步消息,会在今年5月15~16的React Conf公布。

相关推荐
运维帮手大橙子2 小时前
完整的登陆学生管理系统(配置数据库)
java·前端·数据库·eclipse·intellij-idea
_Kayo_3 小时前
CSS BFC
前端·css
二哈喇子!4 小时前
Vue3 组合式API
前端·javascript·vue.js
二哈喇子!6 小时前
Vue 组件化开发
前端·javascript·vue.js
C4程序员6 小时前
北京JAVA基础面试30天打卡03
java·开发语言·面试
chxii6 小时前
2.9 插槽
前端·javascript·vue.js
姑苏洛言7 小时前
扫码点餐小程序产品需求分析与功能梳理
前端·javascript·后端
Freedom风间7 小时前
前端必学-完美组件封装原则
前端·javascript·设计模式
Java技术小馆7 小时前
PromptPilot打造高效AI提示词
java·后端·面试
江城开朗的豌豆7 小时前
React表单控制秘籍:受控组件这样玩就对了!
前端·javascript·react.js