← 返回题目列表

useTransition 和 startTransition 适合解决什么问题?

中等 第 22 / 27 题 更新于 2026/07/29
ReactuseTransitionstartTransitionReact18

简化版

startTransition 用来把某些状态更新标记为非紧急更新,避免它们阻塞输入等紧急更新;useTransition 额外提供 isPending,便于展示过渡中的加载状态。它适合输入联动大列表、复杂 tab 切换等场景。

详细版

典型场景是输入框立即更新,搜索结果列表可以稍后更新。

const [isPending, startTransition] = useTransition()

function onChange(e) {
  const next = e.target.value
  setKeyword(next)
  startTransition(() => {
    setQuery(next)
  })
}

setKeyword 是紧急更新,让输入框跟手;setQuery 触发大列表过滤,标为 transition 后可以被 React 延后或中断。isPending 可以显示“正在更新结果”。它不是防抖,也不会减少计算次数本身。

完整版教学

一、它解决的是紧急和非紧急更新抢主线程

用户输入时,输入框字符显示必须立刻发生。 但根据输入过滤大列表、渲染复杂图表、切换大面板,这些可以稍慢一点。 如果两类更新绑定在一起,同步渲染会让输入卡顿。

一次输入:
更新 input 值 1ms
过滤并渲染列表 80ms
用户感受: 输入卡了 80ms

transition 的思路是告诉 React:输入值很急,列表结果没那么急。 这样 React 可以优先处理输入,后处理列表。

二、startTransition 标记非紧急状态更新

startTransition 包住的状态更新会被标记为 transition。 这些更新可以被更紧急的更新打断。 它适合不需要立即完成但仍要最终展示的 UI 更新。

import { startTransition } from 'react'

function selectTab(tab) {
  setActiveTab(tab)
  startTransition(() => {
    setHeavyPanel(tab)
  })
}
更新是否适合 transition原因
输入框受控值不适合必须立刻反馈
大列表过滤条件适合可以稍后更新
勾选按钮状态通常不适合用户期待立即响应
切换复杂内容区适合可显示 pending

判断标准是用户是否会立刻感知到“没变”。 输入框不立刻变会很糟,搜索结果晚 100ms 通常可接受。

三、useTransition 比 startTransition 多一个 pending 状态

useTransition 返回 [isPending, startTransition]isPending 表示 transition 更新还没完成。 这可以用来展示轻量提示,避免用户以为页面没反应。

const [isPending, startTransition] = useTransition()

return (
  <>
    <input onChange={onChange} />
    {isPending && <span>结果更新中...</span>}
    <SearchList query={query} />
  </>
)

如果列表更新需要 300ms,pending 提示可以帮助用户理解。 如果更新只有 20ms,提示可能闪烁,UI 上可以做延迟展示。

四、它不是防抖,也不是节流

防抖会减少触发次数,例如用户停下 300ms 后才请求。 transition 不一定减少计算次数,它只是降低更新优先级,让紧急渲染有机会先完成。 两者可以配合,但不能混为一谈。

防抖:
10 次输入 -> 1 次请求

transition:
10 次输入 -> 输入优先响应,结果更新可被中断或延后

如果你的瓶颈是频繁请求接口,防抖更直接。 如果瓶颈是本地大列表渲染影响输入,transition 更贴切。

五、transition 内部仍然要避免重计算浪费

标记低优先级不代表计算免费。 如果每次 transition 都同步过滤 100000 条数据,主线程仍然会忙。 工程里通常还要配合 memo、虚拟列表、索引、Web Worker 或分页。

const visible = useMemo(() => {
  return items.filter(item => item.name.includes(query))
}, [items, query])

假设过滤 100000 条需要 50ms,列表渲染需要 70ms。 transition 能让输入先响应,但最终这 120ms 工作仍然存在。 优化总量和优化优先级是两回事。

六、异步边界和数据请求要分清

transition 标记的是 React 状态更新优先级。 它不会自动取消 fetch,也不会自动管理服务端数据缓存。 如果涉及请求,仍需要请求库、缓存、取消和错误处理。

记忆钩子:transition 不是少干活,是把“不急的 UI 更新”排到后面干。

面试中最好用搜索框例子。 先更新输入框,再 transition 更新搜索结果,顺手说明它不是 debounce。

七、常见误区与追问

  • 误区:transition 可以让计算消失。 它调整更新优先级,不会凭空减少计算量。
  • 误区:输入框 value 更新应该放进 startTransition。 受控输入值必须紧急更新,否则会卡手。
  • 误区:useTransition 就是防抖。 防抖减少触发次数,transition 调整渲染优先级。
  • 追问:isPending 有什么用? 用来展示非紧急更新尚未完成的提示或骨架状态。
  • 追问:startTransition 和 useTransition 怎么选? 不需要 pending 状态时可用 startTransition,组件内要展示 pending 用 useTransition
  • 追问:大列表还是卡怎么办? 配合虚拟列表、memo、数据索引、分页或 Worker,减少实际工作量。

八、加强记忆

这题围绕“急不急”回答。输入、点击反馈是急活;大列表、大面板更新是慢活。startTransition 给慢活降优先级,useTransition 还能告诉你慢活是否 pending。别把它说成防抖或性能银弹。