Back

React 19 中的流畅异步过渡

React 19 中的流畅异步过渡

你构建了一个向服务器提交数据的表单。用户点击”保存”按钮,然后两秒钟内什么都没发生。他们再次点击。现在你遇到了重复请求、混乱的 UI 以及一个沮丧的用户。

React 19 通过异步过渡(async transitions)解决了这个问题——这是 React 处理异步更新方式的根本性转变。React 现在可以自动跟踪待处理的工作,而不是手动处理加载状态、错误标志和竞态条件。本文将解释 React 19 中的 useTransition 与 React 18 模式的区别、何时使用这些原语,以及它们如何与新兴的浏览器 API(如 View Transitions)连接。

核心要点

  • React 19 的 startTransition 接受异步函数,在过渡运行期间自动跟踪待处理状态——减少了手动切换 isLoading 的需要。
  • useTransition 关注的是更新优先级,而非动画。将其用于表单提交、搜索过滤器和标签页切换——而不是受控输入或紧急错误状态。
  • useOptimistic Hook 与异步过渡配合良好,可以立即显示预期结果,并在失败时自动回滚。
  • React 的调度器过渡和浏览器的 View Transitions API 解决不同的问题:一个管理更新何时渲染,另一个管理元素在状态之间如何动画化。

startTransition 异步支持如何改变一切

在 React 18 中,startTransition 只接受同步函数。你可以将状态更新标记为低优先级,但异步操作需要单独的加载状态管理。

React 19 改变了这一点。你现在可以直接向 startTransition 传递异步函数:

const [isPending, startTransition] = useTransition()

const handleSubmit = () => {
  startTransition(async () => {
    const result = await saveToServer(data)
    setStatus(result)
  })
}

React 在异步操作运行期间跟踪过渡。isPending 保持 true 直到 React 完成处理过渡工作。

重要提示:await 之后调度的状态更新可能不会总是自动包含在同一个过渡中。如果你需要这些更新保持非紧急状态,请将它们包装在另一个 startTransition 中。

这消除了困扰 React 18 模式的大量样板代码:

React 18 模式React 19 模式
手动 isLoading 状态自动 isPending 跟踪
带错误状态的 try/catch错误边界集成
竞态条件处理内置请求排序

React 19 中的 useTransition:何时使用

当你希望 UI 在昂贵的更新期间保持响应时,使用 useTransition。该 Hook 告诉 React:“如果发生更紧急的事情,此更新可以等待。”

适用场景:

  • 用户可能继续输入的表单提交
  • 触发数据获取的搜索过滤器
  • 加载新内容的标签页切换

跳过过渡的场景:

  • 受控输入值(这些应该立即更新)
  • 需要立即可见的关键错误状态
  • 简单的同步状态更改

关键洞察:过渡关注的是优先级,而非动画。如果用户输入、滚动或执行任何紧急交互,React 将中断待处理的过渡。

React 19 中使用 useOptimistic 的乐观 UI

useOptimistic Hook 与异步过渡自然配合。它让你在服务器确认时立即显示预期结果:

const [optimisticItems, addOptimistic] = useOptimistic(
  items,
  (current, newItem) => [...current, newItem]
)

const handleAdd = () => {
  startTransition(async () => {
    addOptimistic({ id: "temp", text: inputValue })
    await saveItem(inputValue)
  })
}

如果请求失败,React 会自动回滚到之前的状态。这在不需要复杂状态协调逻辑的情况下创建了感知性能改进。

虽然 useOptimistic 与过渡或异步操作配合使用效果最佳,但并非严格要求——根据你的数据流,该 Hook 仍可以独立使用。

调度器过渡 vs. View Transitions API

React 的过渡和浏览器的 View Transitions API 解决不同的问题:

调度器过渡(useTransition)管理 React 何时渲染更新。它们处理优先级和响应性。

View transitions 管理元素在状态之间如何动画化。它们处理视觉连续性。

React 正在试验一个桥接两者的 <ViewTransition> 组件。然而,这仍处于实验阶段。浏览器 API 本身在主流浏览器(包括 Chrome、Edge、Safari 和 Firefox)中具有广泛支持

如果你今天正在探索 view transitions:

  • 使用带特性检测的 document.startViewTransition()
  • 为不支持的浏览器提供优雅的降级方案
  • 避免在生产环境中依赖实验性框架集成

实用指南

应该:

  • 将表单提交和数据变更包装在 startTransition
  • 使用 isPending 禁用按钮并显示加载指示器
  • useOptimistic 结合使用,为可预测的操作提供即时反馈

不应该:

  • 将每个状态更新都包装在过渡中
  • 将过渡用于紧急 UI 反馈,如验证错误
  • 假设 View Transitions API 在所有地方都能工作

结论

React 19 异步过渡消除了困扰 React 18 应用程序的大量手动加载状态逻辑。通过向 startTransition 传递异步函数,你可以获得内置的待处理状态跟踪、更流畅的感知性能以及与现代 React 模式的更好集成。

首先用 useTransition 替换你的手动 isLoading 状态。在即时反馈重要的地方添加 useOptimistic。将实验性 View Transitions 集成留到浏览器支持成熟时再使用。

常见问题

可以。在 React 19 中,从客户端组件触发的 Server Actions 可以包装在 startTransition 中。这让你可以直接从客户端跟踪服务器端变更的待处理状态,无需额外的加载状态变量即可获得自动的 isPending 跟踪。

过渡期间抛出的错误会传播到最近的错误边界(如果存在)。如果没有错误边界,错误将像任何其他渲染错误一样浮现,因此生产应用应确保设置了边界。通过 useOptimistic 进行的任何乐观更新通常会在过渡被放弃时回滚。

可以。虽然通常与过渡或异步操作配对使用,但 useOptimistic 可以独立运行。将其与过渡配对只是在非紧急更新期间提高了感知响应性。

不一定。useTransition 将更新标记为非紧急,这意味着 React 可能会延迟渲染它们。对于需要立即 UI 反馈的情况,如内联验证错误或切换模态框,简单的 useState 布尔值仍然是正确的选择。将过渡保留给响应性比即时性更重要的操作。

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