React 19 Beta新内容前瞻合集(快速版)

2024-04-28 10:12

本文主要是介绍React 19 Beta新内容前瞻合集(快速版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

React v18 发布后,带来了以并发特性为主的各种新 API ( startTransition / useDeferredValue 等 )、新运作模式、及 stream SSR 上的改进等,其相比 React v17 像是一个增量的升级版。

而 React v19 则不然,包含了 大量 细小的、或破坏性的变更。

本文将快速前瞻 React v19 到目前为止( React v19 Beta )的所有变化,部分内容由于涉及层层历史背景,此处只进行简单介绍。

我们默认读者拥有 React <= v18 和 React v18 canary 版本的所有前置知识。

由于 React v18 canary 已迭代很久,本次更新中的很多内容属于历史已公布的内容,故不会重复做展开介绍。

正文

如阅读时间不足,请只关注重点内容,不重要的内容很少会在未来中使用到。

API 变更

新 API :useActionState
  • 重要性:★

  • 参考信息:useActionState 代码例子

此 API 原名为 useFormState ,主要用于联动原生 <form /> 表单提交,现代开发更多使用高级表单库,故此特性不重要。

新 API :useFormStatus
  • 重要性:★

  • 参考信息:useFormStatus 文档

此 API 与 useFormState 联动使用,现代开发更多使用高级表单库,故此特性不重要。

新 API :useOptimistic
  • 重要性:★★

  • 参考信息:useOptimistic 文档

通过此 API 派生其他的 state ,从而在提交动作时,立即乐观更新此值来优化用户视觉上的交互体验。

要实现乐观更新,必然要编写许多额外逻辑,同时现代请求库(如 react-query 、SWR 等)早已提供了乐观更新的功能。然而更多时候,我们没有精力和工时来提升用户体验,过度提升体验反而会造成更多冗余的乐观更新逻辑导致后续维护困难,展示 loading 已经足够,故此 API 不重要,若不是有心为之,则很难用到。

新 API :use
  • 重要性:★★★★★

  • 参考信息:use 代码例子

最重要的 API ,具有两种功能:

  1. 等待 Promise

    • Suspense 内,使用 use(Promise) 获取异步数据,无需自行 throw Promise
    • 在 RSC 和各种 React 状态管理库中已被广泛使用。
    • 其 polyfill 版本已被广泛使用( 等同旧手动触发 Suspense 行为 )。
  2. 代替 useContext()

    • 无视 hooks 不能出现在条件判断内的规则,允许条件性的获取 Context 值。

目前此 API 已经在 React v18 canary 、RSC 、各种基础库内,被广泛使用,是使用最广泛、最重要的 API 之一。

在未来:

  1. 涉及到处理 Promise 数据时:

    • 若想联动 Suspense ,优先使用请求库内和 Suspense 相关的获取数据方法(如 useSuspenseQuery 、SWR Suspense ),避开直接使用 use 造成冗余逻辑。
    • 若不想联动 Suspense ,和以前一样请求库 + 展示 loading 态即可,无需使用 use(Promise)
    • 若为 RSC ,直接使用 use 便捷获取数据即可(若涉及较强的请求设计,如类型支持、同构等,仍需编写较多逻辑)。
  2. 涉及到获取 Context 数据时 :直接使用 use 代替 useContext ,这使得以下代码成为可能:

      if (condition) {value = use(ContextA)} else {value = use(ContextB)}
    
新 API :preXXX 预加载资源
  • 重要性:★★

  • 参考信息:preconnect / prefetchDNS / preinit / preinitModule / preload / preloadModule 文档说明

分类来看:

  1. preconnectprefetchDNS 等 API 将插入 <link rel="preconnect" /> 标签的行为命令化,但由于预加载时机越早越好,等到 React 应用运行后,已经错过了 preconnect 的最好时机,所以编写至 HTML 内或 SSR 仍然是首选方案,此类 API 不重要。

  2. preinit / preload 等 API 将 脚本、样式 的加载命令化,但现代项目开发时已经内部模块化,使用 await import() 等懒加载行为已足够,故除了需要加载外部 脚本、样式 外,此 API 也不重要。

新 API :onCaughtError 全局错误捕获
  • 重要性:★★

  • 参考信息:onCaughtError / onUncaughtError / onRecoverableError 文档说明

这给 React 在全局 ReactDOM.createRoot 挂载时开放了一个全局捕获错误的出口:

ReactDOM.createRoot(document.getElementById('root')!, {onCaughtError: (error, errorInfo) => {// ...},
})

这可以避免在 ErrorBoundary 内部收集错误,而在全局更清真的统一处理(此处只是单纯报告错误,涉及到复杂的 ErrorBoundary 错误恢复和重试,仍然需要编写大量代码)。

注:不可以捕获 React 内的异步逻辑错误。

特性变更

新特性 :ref 将成为 props
  • 重要性:★★★★

  • 参考信息:ref 代码例子

在以前,涉及到 ref 时,因为要使用 forwardRef 并编写大量相关类型,故大多数情况我们会使用回调,回避掉使用 ref ,或使用其他 props 的名字传递 ref ,从而避免 forwardRef 的出现。

在 React v19 中, ref 将成为一个普通的 props ,可以直接在子组件内通过 props.ref 获取到,这是一个开发体验上的较大进步,但请不要滥用 ref 传递,更多时候我们只是为基础组件提供 ref ,或为外部提供较多主动操作方法时才会使用 ref

注:这并不代表 forwardRef 的消失,forwardRef 仍然有效;在历史兼容上,这可能会使得 ...props 的展开中存在意外的 ref ,但综合来看影响不大。

新特性 :Context 等价于 Context.Provider
  • 重要性:★★★

  • 参考信息:Context 代码例子

这是一个开发体验上的优化,以前我们需要提供 Context 时,需要编写为 Context.Provider ,现在直接使用 Context 即可。

注:Context.Provider 仍然有效。

新特性 :<head /> 元信息将被提升
  • 重要性:★

  • 参考信息:代码例子

在以前,我们希望在某个组件内提供页面 <head /> 元信息时,往往使用 react-helmet-async ,而现在 React 将自动提升这些元信息标签(如 <title> 等),将其移动渲染至 <head></head> 内,而不保留在原处。

考虑到 SSR 的完备性,使用第三方库插入元信息仍然更好,所以此特性不重要。

新特性 :带有 加载优先级 的 <script /><style /> 等标签
  • 重要性:★

  • 参考信息:插入 link / meta / script / style / title 文档说明

对于使用 webpack 等打包工具进行模块化开发的现代,除 特别的样式覆盖 或 异步分包、构建工具缺陷 等原因导致对顺序出现 workaround 的需求外,一般我们在业务项目内不会接触到手动管理标签的情况,故此特性不重要。

需要关注的其他变化

回调函数形式的 ref 返回值将变为清理函数
  • 重要性:★

  • 参考信息:ref return cleanup 说明

由于 ref 回调函数使用概率较小(一般在 动画 或 获取布局 等场景下才使用),请格外留意不要在此函数内随意返回值。

React UMD 版本已被删除
  • 重要性:★★★

  • 参考信息:删除 UMD

仍有不少项目希望通过 external React UMD 的方式进行一些依赖外置化加载的设计,但未来 esm 是大势所趋,故 React v19 已删除 UMD 版本。

如还想通过外置形式使用 React ,需改为 esm 的 <script type="module"> 方式使用:

<script type="module">import React from "https://esm.sh/react@beta"import ReactDOM from "https://esm.sh/react-dom@beta/client"...
</script>
内部 SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED 变量已改名
  • 重要性:★★

  • 参考信息:SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED 改名

获取 React 内部信息的出口 SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED 已被重命名为 _DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE ,虽然 SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED 名字上不推荐用户使用,但迄今为止该出口仍被不少库(如 可视化 相关)使用 。

故当此变量改名后,一些第三方库不更新的话,会影响到使用,需要多加关注。

useRef 必须传入默认值
  • 重要性:★★★

  • 参考信息:useRef 入参更改说明

React v19 要求 useRef(defaultValue) 传入一个默认值,这会影响到所有历史 useRef() 未设定默认值的调用写法。

在以前,我们往往会通过 useRef<HTMLInputElement>(null!) 技巧 避免类型提示为空,因为此处 ref 必定存在,若存在默认值或采用技巧,则不存在此变动带来的问题,但相当一部分人并不会采用 React TypeScript 技巧 ,请多加留意。

各种不重要的小变化

API 相关
  • ReactDOM.render / ReactDOM.hydrate 旧版渲染应用 API 已被删除( 链接 )

  • useDeferredValue 支持设定默认值( 链接 )

  • React.createFactory 已被删除( 链接 )

  • react-test-renderer/shallow 导出位置已被更改( 链接 )

  • unmountComponentAtNode 旧版卸载节点 API 已被删除( 链接 )

  • ReactDOM.findDOMNode API 已被删除( 链接 )

特性相关
  • 更好的 web components 支持( 链接 )

    注:这是一个较瞩目的新特性,但大多数人很少使用 web component ,故只有特定用户群体才值得去关注。

体验相关
  • 水合出现差异时,报错信息更友好( 链接 )。

  • 优化了控制台错误打印的格式( 链接 )

  • useLayoutEffect 在服务端运行的警告已被删除( 链接 )

Class 组件相关
  • Class 组件的 propTypes / defaultProps 已被删除( 链接 )

  • Class 组件的 getChildContext 已被删除( 链接 )

  • Class 组件的字符串 ref="string" 已被删除( 链接 )

函数组件相关
  • 函数组件的 render() 渲染方式已被删除( 链接 )
测试相关
  • act 函数导出位置已转移至 react ( 链接 )

  • react-test-renderer 已弃用( 非删除, 链接 )

    注:此包以前可能用于一些简单的组件测试,但现在已被弃用,请在所有 React 的测试中统一使用 RTL ( @testing-library/react ),这将是官方推荐的唯一测试库。

类型相关
  • ReactElement 类型被调整( 链接 )

  • 限定 React JSX 类型的命名空间( 链接 )

    注:为了避免各种 JSX 的类型在全局冲突,Vue v3.4 也限制了自己的命名空间。

  • useReducer 类型改进( 链接 )

新 React 版本信息

伴随 React v19 Beta 的发布,React v18.3 也一并发布。

React v18.3

相比最后一个 React v18 的版本 v18.2v18.3 添加了一些警告提示,便于尽早发现问题,从而在升级 React v19 时更容易。

由于 React v19 包含的各种小变化数量较多,仅仅依靠 React v18.3 中的提示可能仍力不从心,如需更容易的升级,你可能还需要依靠各种针对 React v19 的 eslint 规则和 codemod 来达成升级预期。

React v20

目前已知内容:

  1. React compiler (编译优化器,如 React forget )不等于 React v19

  2. Activity ( 原 Offscreen )可能在 React v20 推出。

总结

关于 RSC

由于 RSC 已经由 Next.js 掌控,同时目前社区各种自制 RSC 框架各自为战(特性与实现七零八落),仍在不断发展中,最终 RSC 会怎样,其 发展方向、拥有特性 等一切与 Next.js 对齐即可,使用 RSC 目前的不二之选仅为 Next.js ,故文本未谈及 RSC 相关内容,如有兴趣可自行了解(如 taintpostponeuse server 、stream 数据传输支持 等)。

升级 React v19

在以往的 React v16v17v18 的升级中,我们没有遇到太多升级阻力,更多的是增量特性升级,但 React v19 包含的小变化较多,对于较大项目的升级可能会较困难(由于 React v19 仍未正式发布,故我们不断期待更多升级经验的分享与学习)。

参考资料

以下链接为 以上内容 中 一部分的相关参考资料(仅包含可访问的链接),若无额外精力,无需关注以下内容:

  • 博文:React v19 Beta 发布( 链接 )

  • 博文:React v19 升级指南( 链接 )

  • 变更日志:React v18.3 Release Changelog ( 链接 )

  • 原始 PR :删除 UMD 构建( 链接 )

  • React v19 支持 web component 的设计与讨论 RFC ( 链接 )

  • 原始 PR :React v18.3 ( 链接 )

  • 原始 PR :重命名 SECRET INTERNALS 变量名 ( 链接 )

  • 原始 PR :删除 Class 组件的 defaultProps ( 链接 )

  • 原始 PR :改进水合不匹配时的警告内容( 链接 )

  • 原始 PR :useActionState ( 链接 )

  • 原始 PR :ref 调整为普通 props ( 链接 )

这篇关于React 19 Beta新内容前瞻合集(快速版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/942978

相关文章

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

shell脚本快速检查192.168.1网段ip是否在用的方法

《shell脚本快速检查192.168.1网段ip是否在用的方法》该Shell脚本通过并发ping命令检查192.168.1网段中哪些IP地址正在使用,脚本定义了网络段、超时时间和并行扫描数量,并使用... 目录脚本:检查 192.168.1 网段 IP 是否在用脚本说明使用方法示例输出优化建议总结检查 1

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用

Rust中的Option枚举快速入门教程

《Rust中的Option枚举快速入门教程》Rust中的Option枚举用于表示可能不存在的值,提供了多种方法来处理这些值,避免了空指针异常,文章介绍了Option的定义、常见方法、使用场景以及注意事... 目录引言Option介绍Option的常见方法Option使用场景场景一:函数返回可能不存在的值场景

详解Spring Boot接收参数的19种方式

《详解SpringBoot接收参数的19种方式》SpringBoot提供了多种注解来接收不同类型的参数,本文给大家介绍SpringBoot接收参数的19种方式,感兴趣的朋友跟随小编一起看看吧... 目录SpringBoot接受参数相关@PathVariable注解@RequestHeader注解@Reque

使用Vue.js报错:ReferenceError: “Vue is not defined“ 的原因与解决方案

《使用Vue.js报错:ReferenceError:“Vueisnotdefined“的原因与解决方案》在前端开发中,ReferenceError:Vueisnotdefined是一个常见... 目录一、错误描述二、错误成因分析三、解决方案1. 检查 vue.js 的引入方式2. 验证 npm 安装3.

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

python解析HTML并提取span标签中的文本

《python解析HTML并提取span标签中的文本》在网页开发和数据抓取过程中,我们经常需要从HTML页面中提取信息,尤其是span元素中的文本,span标签是一个行内元素,通常用于包装一小段文本或... 目录一、安装相关依赖二、html 页面结构三、使用 BeautifulSoup javascript

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义