Back

React 19 对异步渲染的改变

React 19 对异步渲染的改变

React 18 引入了并发渲染。React 19 并没有替换这个基础——它在此基础上构建,为你之前需要手动实现的异步工作流提供了标准化模式。

如果你一直在管理 isPending 状态、协调异步操作中的错误处理,或手动实现乐观更新,React 19 为所有这些场景提供了一流的 API。本文将解释实际发生了什么变化,以及你的思维模型应该如何转变。

作为参考,这里讨论的所有 API 都记录在 React 官方文档中:https://react.dev

核心要点

  • React 19 在 React 18 的并发渲染基础上,为常见异步模式添加了更高级的抽象
  • startTransition 现在接受异步函数,这些在 React 文档中被正式称为 Actions
  • useActionState 消除了表单处理的样板代码,内置了 pending 状态和错误管理
  • useOptimistic 标准化了乐观更新,回滚由规范状态驱动
  • use() API 让你可以在渲染期间读取 promise,但需要缓存的或与 Suspense 兼容的 promise

核心转变:从手动管道到内置模式

React 18 给了我们并发渲染引擎。React 19 给了我们使其实用的抽象。

以前,处理异步表单提交意味着要同时操作多个状态变量:

const [isPending, setIsPending] = useState(false)
const [error, setError] = useState(null)

const handleSubmit = async () => {
  setIsPending(true)
  try {
    await submitData()
  } catch (e) {
    setError(e)
  } finally {
    setIsPending(false)
  }
}

React 19 Actions 完全消除了这些样板代码。

React 19 Actions 和异步 Transitions

最大的变化是 startTransition 现在接受异步函数。在 React 19 中,这些异步过渡函数在 React 文档中被正式称为 Actions

const [isPending, startTransition] = useTransition()

const handleSubmit = () => {
  startTransition(async () => {
    const error = await updateName(name)
    if (error) {
      setError(error)
      return
    }
    // 成功时执行导航或状态更新
  })
}

React 19 会为你跟踪 pending 过渡状态,然后你可以通过 useTransitionuseActionState 等 API 显式读取。startTransition 内部的所有状态更新会批量处理,当异步工作完成时产生单次重新渲染。这避免了 isPending 为 false 但错误状态尚未应用的中间状态。

useActionState:专为表单处理而设计

对于表单场景,useActionState 提供了内置的 pending 状态和结果管理:

const [error, submitAction, isPending] = useActionState(
  async (previousState, formData) => {
    const error = await updateName(formData.get("name"))
    if (error) return error
    // 成功时执行导航或更新应用状态
    return null
  },
  null
)

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

React 现在通过集成的 pending 和结果状态处理增强了原生表单的 action 属性。

useOptimistic:即时 UI 反馈

React 19 通过 useOptimistic 标准化了乐观更新:

const [optimisticName, setOptimisticName] = useOptimistic(currentName)

const submitAction = async (formData) => {
  const newName = formData.get("name")
  setOptimisticName(newName) // UI 立即更新
  const result = await updateName(newName)
  onUpdateName(result)
}

当 action 解析后父组件使用规范状态重新渲染时,React 会将 optimisticName 恢复为 currentName。对于失败的 action,确保你的父状态保持不变,以便乐观值正确回滚。

React Suspense 变化和 use() API

use() API 让你可以在渲染期间直接读取 promise。与 hooks 不同,它可以在条件语句和循环中使用:

function Comments({ commentsPromise }) {
  const comments = use(commentsPromise)
  return comments.map(comment => <p key={comment.id}>{comment}</p>)
}

当 promise 处于 pending 状态时,use() 会挂起组件。将其包装在 Suspense 边界中以显示后备 UI。

重要约束:use() 不支持在渲染期间创建的 promise。promise 必须被缓存或来自与 Suspense 兼容的源。你也不能在 try-catch 块内使用 use()——错误边界会处理拒绝。

在支持服务器的环境中,React 文档建议优先使用 async/await 来处理数据获取语义,主要将 use() 用于消费已管理的 promise。

什么没有改变

React 并发 UI 模式——底层调度、可中断渲染和优先级系统——仍然是 React 18 的基础。React 19 没有引入新的并发概念。它提供了利用现有并发能力的更高级 API。

思维模型的转变不在于理解新的渲染机制。而在于认识到 React 现在处理了你以前自己管理的异步 UI 状态。

实际影响

停止手动管理 pending 状态。 使用 useTransitionuseActionState 而不是手动的 isPending 变量。

对变更操作使用 Actions。 任何包装在 startTransition 中的异步函数都会成为具有过渡感知调度的 Action。

使用 useOptimistic 实现响应式 UI。 这个模式现在已经标准化,不再需要临时实现。

use() 与 Suspense 配对进行数据获取。 但要记住缓存要求——这在管理 promise 稳定性的框架或库中效果最好。

结论

React 19 的异步渲染不是一个新范式。它是使并发 React 对日常异步工作流实用的缺失抽象层。通过为 pending 状态、表单处理、乐观更新和 promise 解析提供内置 API,React 19 消除了开发者自 React 18 引入并发渲染以来一直在编写的样板代码。基础保持不变——改变的是这些模式变得多么易于访问和标准化。

常见问题

可以。Actions 在任何 React 19 应用程序中都可以工作。虽然像 Next.js 这样的框架提供了额外的服务器端集成,但核心 API(如带异步函数的 useTransition、useActionState 和 useOptimistic)在客户端 React 应用中无需任何框架依赖即可运行。

不完全需要。当父组件使用未更改的规范状态重新渲染时,useOptimistic 会恢复到原始值。你必须确保失败的 action 不会更新该状态,以便正确进行回滚。

不一定。useTransition 适用于非紧急更新,你希望 React 保持当前 UI 的响应性。对于应该阻止交互的关键加载指示器,传统的 useState 模式可能仍然是合适的。

技术上可以,但需要仔细管理 promise。传递给 use() 的 promise 必须在渲染之间保持稳定,这意味着你不能在渲染期间创建它。使用缓存层、数据获取库或框架级数据加载来确保 promise 的稳定性。

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay