React 19 版本有哪些新特性

操作

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

例如,你可以在 `useState` 中处理待处理和错误状态:

// Before Actions
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, setIsPending] = useState(false);

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

  return (
    
setName(event.target.value)} /> {error &&

{error}

}
); }

在 React 19 中,我们添加了在转换中使用异步函数的支持,以自动处理待处理状态、错误、表单和乐观更新。

例如,您可以使用 `useTransition` 来处理待处理状态:

// 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 (
    
setName(event.target.value)} /> {error &&

{error}

}
); }

异步转换将立即将“isPending”状态设置为 true,发出异步请求,并在任何转换后将“isPending”切换为 false。这允许您在数据发生变化时保持当前 UI 响应和交互。

笔记

按照惯例,使用异步转换的功能称为“动作”。

操作会自动为您管理提交数据:

待处理状态:操作提供待处理状态,该状态从请求开始时开始,并在提交最终状态更新时自动重置。

乐观更新:操作支持新的“useOptimistic”钩子,因此您可以在提交请求时向用户显示即时反馈。

错误处理:操作提供错误处理,以便您可以在请求失败时显示错误边界,并自动将乐观更新恢复为其原始值。

形式:` ` 元素现在支持将函数传递给 `action` 和 `formAction` 属性。将函数传递给 `action` 属性默认使用 Actions,并在提交后自动重置表单。

在 Actions 的基础上,React 19 引入了 `useOptimistic` 来管理乐观更新,并引入了新的钩子 `React.useActionState` 来处理 Actions 的常见情况。在 `react-dom` 中,我们添加了 ``Actions 来自动管理表单,并添加了 `useFormStatus` 来支持表单中 Actions 的常见情况。

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

// Using 
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 ( {error &&

{error}

}
); }

在下一部分中,我们将分解 React 19 中的每个新 Action 功能。

新钩子:useActionState

为了使 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 时,`useActionState` 将返回 Action 的最后结果作为 `data`,并将 Action 的待处理状态作为 `pending`。

笔记

React.useActionState 以前在 Canary 版本中被称为 ReactDOM.useFormState,但我们已将其重命名并弃用了 useFormState。

请参阅#28491 以了解更多信息。

有关更多信息,请参阅“useActionState”文档。

React DOM:操作

Actions 还与 React 19 的 ``react-dom`` 新功能集成。我们添加了将函数作为 ``、`` 的 ``action`` 和 ``formAction`` 属性传递的支持。`,和 `` 元素使用以下操作自动提交表单:

当 `` Action 成功执行时,React 会自动重置不受控组件的表单。如果需要手动重置 ``,可以调用新的 ``requestFormReset`` React DOM API。

有关详细信息,请参阅 `react-dom` 文档中的 ``, ``,和 ``。

React DOM:新钩子:useFormStatus

在设计系统中,编写需要访问其所在位置信息的设计组件很常见,而无需深入研究组件的 props。这可以通过 Context 完成,但为了使常见情况更容易,我们添加了一个新的钩子 `useFormStatus`:

import {useFormStatus} from 'react-dom';

function DesignButton() {
  const {pending} = useFormStatus();
  return 

`useFormStatus` 读取父级的状态,就好像表单是一个上下文提供程序一样。

欲了解更多信息,请参阅 `react-dom` 文档中的 `useFormStatus`。

新的钩子:useOptimistic

执行数据变异时的另一个常见 UI 模式是在异步请求进行时乐观地显示最终状态。在 React 19 中,我们添加了一个名为“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 (
    
      

Your name is: {optimisticName}

); }

`useOptimistic` 钩子将在 `updateName` 请求进行时立即渲染 `optimisticName`。当更新完成或出错时,React 将自动切换回 `currentName` 值。

有关更多信息,请参阅“useOptimistic”的文档。

新 API:使用

在 React 19 中,我们引入了一个新的 API 来读取渲染中的资源:“use”。

例如,你可以使用 `use` 读取一个承诺,React 将会暂停直到该承诺解决:

import {use} from 'react';

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

{comment}

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

笔记

使用不支持在渲染中创建的承诺。

如果你尝试将在 render 中创建的 promise 传递给 use,React 会发出警告:

Error
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.

要解决此问题,您需要从支持缓存承诺的 Suspense 驱动库或框架传递承诺。未来我们计划推出一些功能,以便更轻松地在渲染中缓存承诺。

您还可以使用“use”来读取上下文,这样您就可以有条件地读取上下文,例如在提前返回之后:

import {use} from 'react';
import ThemeContext from './ThemeContext'

function Heading({children}) {
  if (children == null) {
    return null;
  }

  // This would not work with useContext
  // because of the early return.
  const theme = use(ThemeContext);
  return (
    

{children}

); }

`use` API 只能在 render 中调用,类似于 hooks。与 hooks 不同,`use` 可以有条件地调用。未来我们计划支持更多使用 `use` 在 render 中消耗资源的方式。

有关详细信息,请参阅“use”文档。

新的 React DOM 静态 API

我们向 `react-dom/static` 添加了两个新的 API,用于静态站点生成:

  • 预渲染
  • prerenderToNodeStream
  • 这些新 API 通过等待数据加载以生成静态 HTML 来改进 `renderToString`。它们旨在与 Node.js Streams 和 Web Streams 等流式环境配合使用。例如,在 Web Stream 环境中,您可以使用 `prerender` 将 React 树 `预渲染` 为静态 HTML:

    import { prerender } from 'react-dom/static';
    
    async function handler(request) {
      const {prelude} = await prerender(, {
        bootstrapScripts: ['/main.js']
      });
      return new Response(prelude, {
        headers: { 'content-type': 'text/html' },
      });
    }

    Prerender API 将等待所有数据加载完毕,然后返回静态 HTML 流。流可以转换为字符串,也可以通过流式响应发送。它们不支持在加载时流式传输内容,这

    React 服务器组件

    服务器组件

    服务器组件是一个新选项,允许在捆绑之前在独立于客户端应用程序或 SSR 服务器的环境中提前渲染组件。这个独立的环境就是 React 服务器组件中的“服务器”。服务器组件可以在 CI 服务器上构建时运行一次,也可以使用 Web 服务器针对每个请求运行。

    React 19 包含 Canary 频道中包含的所有 React Server Components 功能。这意味着 Server Components 附带的库现在可以将 React 19 作为对等依赖项,并使用“react-server”导出条件,以便在支持全栈 React 架构的框架中使用。