在这里插入图片描述

🤖 作者简介:水煮白菜王 (juejin/csdn同名),一位资深前端劝退师 👻
👀 文章专栏: 前端专栏 ,记录一下平时在博客写作中,总结出的一些开发技巧✍。
感谢支持💕💕💕

React 19 的第一个版本是在2024年4月发布的,具体来说是4月25日发布了版本号为19.0.0-Beta的测试版。这个版本主要是面向各大库以确保它们与 React 19 的兼容性。因此,对于开发者而言,建议先升级至最新的稳定版… 所以

React v19,他来了!🚀

在这里插入图片描述

React 团队于 2024 年 12 月 5 日正式发布了 React v19 稳定版,现已在 npm 上可用。开发者们可以通过 React 19 升级指南获取详细的升级步骤和注意事项。本文将介绍在React v19 版本中给大家都带来了哪些新特性和改进。

React v19 新特性一览及改进

功能名称描述
ActionsActions 现在支持异步数据更新操作,允许在 Transition 中执行副作用(如 API 请求)。每个 Transition 可以包含一个或多个 Actions,这些 Actions 在后台更新状态,最后通过一次提交来刷新 UI。此外,Actions 支持错误处理和乐观更新useOptimistic,确保用户界面在等待后台任务完成时保持响应。
useActioState这是一个新的 Hook,用于在 Transition 中调度 Actions进行排序。它提供了访问 Action 的状态和 pending 状态的能力。useAction 接受一个 reducer 函数,用于调用 Actions,以及一个初始状态对象。还可以接受一个可选字符串参数,当操作传递给 form prop 时,该字符串可用于表单中的渐进式增强。
useOptimistic此 Hook 用于在过渡期间立即更新状态,提供一种乐观更新的方式。它返回当前状态及一个 set 函数,可以在过渡中调用来即时应用预期的最终状态值。一旦过渡完成,状态会自动更新为实际的新值。
use这是 React 19 引入的一个新 API,允许在渲染过程中读取资源。它可以接受 Promise 或 Context 对象。如果提供的是 Promise,则 React 将暂停渲染,直到 Promise 解析完成。此功能只能在 render 方法中使用,但可以根据条件调用。
ref 作为 propRefs 现在可以直接作为 props 传递给子组件,无需显式使用 forwardRef。这简化了 ref 的传递方式,使得代码更加简洁。
Suspense 同级预热当组件挂起(例如等待数据加载)时,React 不再等待整个同级树渲染完毕,而是立即提交最近的 Suspense 边界的回退内容。之后,React 会继续为其他暂停的兄弟组件安排渲染,提前启动惰性请求,从而加快整体渲染速度。
这项改进显著提升了用户体验,特别是在加载多个异步组件时。通过尽早展示部分可用的内容,用户可以更快地开始与页面互动,而不需要等待所有内容都准备好。
简洁的 <Context> 写法在 React 19 中,引入了更简洁的 Context 写法,可以直接使用 <Context> 代替 <Context.Provider>,简化了上下文提供者的使用。
ref 的回调清理React 19 支持从回调返回清理函数,允许在组件卸载时执行回调清理逻辑,确保资源释放和避免内存泄漏。
Document Metadata 支持现在 React v19 原生支持 <title><meta><link> 等文档元数据标签。这些标签可直接在组件中声明,React 会自动将它们提升至 <head> 或 document 部分,简化 SEO 和元数据管理逻辑,确保与服务端渲染、客户端渲染、流式 SSR 和服务器组件兼容。
增强的样式表管理React 19 增强了样式表的加载管理,通过引入 precedence 属性,React 可以动态调整样式表的插入顺序,确保正确的样式覆盖。此外,React 解决了由于样式优先规则导致的复杂性,允许在组件内实现可组合性的样式表功能。React 现在能够管理 DOM 中样式表(无论是外部 <link rel="stylesheet" href="..."> 还是内联 <style>...</style>)的插入位置,并提供与客户端上的并发渲染和服务器上的流式渲染的更深入集成。如果你告诉 React 你的样式表,它将自动处理样式表的加载顺序,确保在显示依赖于这些样式规则的内容之前加载必要的样式表(特别是外部样式表)。
异步脚本支持在 React 19 中,增强了对异步脚本的支持,允许在组件树的任何位置渲染脚本,并确保它们在所有渲染环境中被去重,从而只加载和执行一次,即使由多个组件渲染。这简化了脚本管理,避免了重复实例和重新定位的问题。
预加载资源支持React 19 引入了多项新 API,用于高效加载和预加载浏览器资源,从而简化构建高性能应用的过程。这些 API 确保资源加载不会成为用户体验的瓶颈,提供流畅、无阻碍的出色体验。
改进的错误处理React 19 改进了错误处理机制,消除了重复错误记录,并提供了处理捕获和未捕获错误的选项。现在,当渲染过程中出现错误并被 Error Boundary 捕获时,React 只会记录一次错误信息,并包含所有相关细节,避免了之前版本中多次抛出错误(如原始错误和自动恢复失败)的情况。此外,React 提供了关于错误发生位置的详细信息,帮助开发者更轻松地诊断和解决问题。
自定义元素支持React 19 增加了对自定义元素的全面支持,并通过了 Custom Elements Everywhere 的所有测试。这一改进解决了过去版本中使用自定义元素的困难,确保了 React 组件与 Web Components 标准无缝集成。使开发者能够更轻松地创建和使用自定义 HTML 元素,提升应用程序的灵活性和可维护性。
更多更新内容 👉react-blogGitHub发行版本v19.0.0

Actions:

React 应用程序中的一个常见用例是执行数据更改,然后更新状态作为响应。例如,当用户提交表单以更改其名称时,您将发出 API 请求,然后处理响应。过去,您需要手动处理待处理状态、错误、乐观更新和顺序请求。

在 React 19 中,增加了对在 transition 中使用异步函数的支持,以自动处理待处理Pending状态、错误、表单和乐观更新(useOptimistic)。

异步数据更新操作Actions,会自动管理提交数据

  • Pending 待处理状态:操作提供待处理状态,该状态从请求开始时开始,并在提交最终状态更新时自动重置。
  • Optimistic 更新:Actions 支持新的 useOptimistic 钩子,因此您可以在提交请求时向用户显示即时反馈。
  • 错误处理:操作提供错误处理,因此您可以在请求失败时显示 Error Boundaries,并自动将乐观更新恢复为其原始值。
  • Forms: 元素现在支持将函数传递给 和 props。将函数传递给 props 默认使用 Actions,并在提交后自动重置表单。
    此功能增强了 Transitions 的灵活性,使其能够更好地处理复杂的 UI 更新逻辑。
// Using pending state from Actions
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, startTransition] = useTransition();

  const handleSubmit = () => {
    startTransition(async () => {
      const error = await updateName(name);
      if (error) {
        setError(error);
        return;
      } 
      redirect("/path");
    })
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}

New hook: useActionState

React 19 构建在 Actions 之上,引入了 useOptimistic 来管理乐观更新,并引入了一个新的钩子 React.useActionState 来处理 Action 的常见情况。在添加 Actions 来自动管理表单,并使用 useFormStatus 来支持表单中 Actions 的常见情况。
通过这个 Hook,开发者可以在不直接管理复杂状态的情况下轻松地触发 Actions,并跟踪它们的状态变化。这对于构建交互性强的应用程序特别有用。

在 React 19 中,上面的例子可以简化为:

// Using <form> Actions and useActionState
function ChangeName({ name, setName }) {
  const [error, submitAction, isPending] = useActionState(
    async (previousState, formData) => {
      const error = await updateName(formData.get("name"));
      if (error) {
        return error;
      }
      redirect("/path");
      return null;
    },
    null,
  );

  return (
    <form action={submitAction}>
      <input type="text" name="name" />
      <button type="submit" disabled={isPending}>Update</button>
      {error && <p>{error}</p>}
    </form>
  );
}

为了简化 Actions 的常见情况,新增了一个名为 :useActionState

const [error, submitAction, isPending] = useActionState(
  async (previousState, newName) => {
    const error = await updateName(newName);
    if (error) {
      // You can return any result of the action.
      // Here, we return only the error.
      return error;
    }

    // handle success
    return null;
  },
  null,
);

useActionState接受一个函数(“Action”),并返回一个包装好的 Action 来调用。这之所以有效,是因为 Actions 组合。调用包装的 Action 时,将返回 Action 的最后一个结果为 ,并将 Action 的待处理状态返回为 。useActionState data pending

注意:React.useActionState之前在 Canary 版本中调用,但已重命名并弃用 。ReactDOM.useFormStateuseFormState 。 useActionState文档

New hook: useOptimistic

这种方法提高了用户体验,因为用户不必等待服务器响应即可看到更改的结果

执行数据更改时,另一种常见的 UI 模式是在异步请求进行时乐观地显示最终状态。在 React 19 中,新增了一个名为 new hook 来简化此操作:useOptimistic

function ChangeName({currentName, onUpdateName}) {
  const [optimisticName, setOptimisticName] = useOptimistic(currentName);

  const submitAction = async formData => {
    const newName = formData.get("name");
    setOptimisticName(newName);
    const updatedName = await updateName(newName);
    onUpdateName(updatedName);
  };

  return (
    <form action={submitAction}>
      <p>Your name is: {optimisticName}</p>
      <p>
        <label>Change Name:</label>
        <input
          type="text"
          name="name"
          disabled={currentName !== optimisticName}
        />
      </p>
    </form>
  );
}

当请求正在进行时,钩子将立即呈现。当更新完成或出错时,React 会自动切换回该值。useOptimistic optimisticName updateName currentName. useOptimistic 文档

新API: use

此 API 的引入简化了从服务器获取数据的过程,同时保证了良好的用户体验。通过让 React 处理加载状态,开发者可以专注于构建应用程序的核心逻辑。

例如,你可以用 来读取一个 promise,React 会 Suspend 直到 promise 解析:use

import {use} from 'react';

function Comments({commentsPromise}) {
  // `use` will suspend until the promise resolves.
  const comments = use(commentsPromise);
  return comments.map(comment => <p key={comment.id}>{comment}</p>);
}

function Page({commentsPromise}) {
  // When `use` suspends in Comments,
  // this Suspense boundary will be shown.
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Comments commentsPromise={commentsPromise} />
    </Suspense>
  )
}

注意:use不支持在 render 中创建的 Promise。
如果你尝试将 render 中创建的 promise 传递给 ,React 会发出警告:
A component was suspended by an uncached promise. Creating promises inside a Client Component or hook is not yet supported, except via a Suspense-compatible library or framework.
要修复,需要从支持 Promise 缓存的 suspense 驱动的库或框架中传递一个 Promise。React官方后面会计划发布功能,以便更轻松地在 render 中缓存 promise。

Server Components支持 ( RSC)

React 19 的服务器组件提供了一种全新的渲染模式,在服务器上提前渲染组件,减少了客户端的渲染负担,并且无需引入额外工具链即可与现有项目无缝集成,支持在构建时或请求时生成组件。

React 19 中的改进

ref作为 prop

这一改变减少了不必要的样板代码,使 ref 的使用更加直观和方便,对于需要直接操作 DOM 元素的情况尤其有帮助。

从 React 19 开始,你现在可以作为函数组件的 prop 进行访问:ref

function MyInput({placeholder, ref}) {
  return <input placeholder={placeholder} ref={ref} />
}

//...
<MyInput ref={ref} />

支持 <Context>

在 React v19 中,引入了简洁的 Context 写法,你可以渲染为 provider 而不是 :<Context><Context.Provider>,可以直接使用 <Context> 代替 <Context.Provider>

const ThemeContext = createContext('');

function App({children}) {
  return (
    <ThemeContext value="dark">
      {children}
    </ThemeContext>
  );  
}

新的 Context providers 可以使用,React官方后面将发布一个 codemod 来转换现有的 providers。React官方在后面的版本中,会弃用 <Context><Context.Provider>

ref 的回调清理

React 19 支持从回调返回清理函数,允许在组件卸载时执行回调清理逻辑

<input
  ref={(ref) => {
    // ref created

    // NEW: return a cleanup function to reset
    // the ref when element is removed from DOM.
    return () => {
      // ref cleanup
    };
  }}
/>

支持Document Metadata

在 HTML 中,文档元数据标记保留用于放置在文档的部分中。在 React 中,决定哪些元数据适合应用程序的组件可能离你渲染的地方很远,或者 React 根本不渲染。过去,这些元素需要手动插入到 effect 中,或者通过 react-helmet 等库插入,并且在服务器渲染 React 应用程序时需要小心处理。
现在React v19 原生支持 <title><meta><link> 等文档元数据标签,这些标签可直接在组件中声明,React 会自动将资源提升至 <head> 或 document 部分,简化 SEO 和元数据管理逻辑,确保与服务端渲染、客户端渲染、流式 SSR 和服务器组件兼容。

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>
  );
}

注意:在开发上有可能仍然需要一个 Metadata library库,对于简单的用例,将文档元数据呈现为标记可能比较合适,但库可以提供更强大的功能,例如根据当前路由使用特定元数据覆盖通用元数据。这些功能使 react-helmet 等框架和库更容易支持元数据标签,而不是直接替换。

支持stylesheets样式表

在 React 19 中,增强了样式表的加载管理,通过引入 precedence 属性,React 可以动态调整样式表的插入顺序,确保正确的样式覆盖。此外,React 解决了由于样式优先规则导致的复杂性,允许在组件内实现可组合性的样式表功能。
React 现在能够管理 DOM 中样式表(无论是外部 <link rel="stylesheet" href="..."> 还是内联 <style>...</style>)的插入位置,并提供与客户端上的并发渲染和服务器上的流式渲染的更深入集成。如果你告诉 React 你的样式表,它将自动处理样式表的加载顺序,确保在显示依赖于这些样式规则的内容之前加载必要的样式表(特别是外部样式表)。

function ComponentOne() {
  return (
    <Suspense fallback="loading...">
      <link rel="stylesheet" href="foo.css" precedence="default" />
      <link rel="stylesheet" href="bar.css" precedence="high" />
      <article class="foo-class bar-class">
        {...}
      </article>
    </Suspense>
  )
}

function ComponentTwo() {
  return (
    <div>
      <p>{...}</p>
      <link rel="stylesheet" href="baz.css" precedence="default" />  <-- will be inserted between foo & bar -->
    </div>
  )
}

支持异步async脚本

在 React 19 中,增强了对异步脚本的支持,允许在组件树的任何位置渲染脚本,并确保它们在所有渲染环境中被去重,从而只加载和执行一次,即使由多个组件渲染。这简化了脚本管理,避免了重复实例和重新定位的问题。

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>
}

支持预加载资源

React 19 引入了多项新 API,用于高效加载和预加载浏览器资源,从而简化构建高性能应用的过程。这些 API 确保资源加载不会成为用户体验的瓶颈,提供流畅、无阻碍的出色体验。

import { prefetchDNS, preconnect, preload, preinit } from 'react-dom'
function MyComponent() {
  preinit('https://.../path/to/some/script.js', {as: 'script' }) // loads and executes this script eagerly
  preload('https://.../path/to/font.woff', { as: 'font' }) // preloads this font
  preload('https://.../path/to/stylesheet.css', { as: 'style' }) // preloads this stylesheet
  prefetchDNS('https://...') // when you may not actually request anything from this host
  preconnect('https://...') // when you will request something but aren't sure what
}
<!-- the above would result in the following DOM/HTML -->
<html>
  <head>
    <!-- links/scripts are prioritized by their utility to early loading, not call order -->
    <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>

更好的 Error报告及hydration错误改进

React 19 改进了错误处理机制,消除了重复错误记录,并提供了处理捕获和未捕获错误的选项。现在,当渲染过程中出现错误并被 Error Boundary 捕获时,React 只会记录一次错误信息,并包含所有相关细节,避免了之前版本中多次抛出错误(如原始错误和自动恢复失败)的情况。此外,React 提供了关于错误发生位置的详细信息,提供更详细的差异化日志,帮助开发者更轻松地诊断和解决问题。

一个错误信息,其中包含所有错误信息,减少冗余错误日志
在这里插入图片描述
在这里插入图片描述

支持自定义元素

React 19 新增了对自定义元素的全面支持,完全兼容 Custom Elements Everywhere 的所有测试。这一改进解决了过去版本中使用自定义元素的困难,确保了 React 组件与 Web Components 标准无缝集成。使开发者能够更轻松地创建和使用自定义 HTML 元素,提升应用程序的灵活性和可维护性。

在 React 19 中,新增了对在客户端和 SSR 期间工作的属性的支持,策略如下:

  • 服务器端渲染:如果其类型是 string、number 或等原始值或值为 true ,则传递给自定义元素的 props 将呈现为属性。具有非原始类型(如 object、symbol、 function或 value)的 props 将被省略。
  • 客户端渲染:与 Custom Element 实例上的属性匹配的 props 将被分配为 properties,否则它们将被分配为 attributes。

React 19 引入了许多新特性,旨在提升开发体验、性能和灵活性。本文介绍了部分新增功能和对现有功能的优化改进,帮助开发者更好地理解和利用这些更新。

更多的更新内容请阅读 官方博客文档GitHub发行版本v19.0.0

在这里插入图片描述
如果你觉得这篇文章对你有帮助,请点赞 👍、收藏 👏 并关注我!👀
在这里插入图片描述

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐