标准答案

  1. useTransition 返回 isPending 和 startTransition,可以把一组更新标记为低优先级。
  2. 适合场景是用户输入或点击要立即响应,但由它触发的大列表渲染、路由切换或重计算可以延后。
  3. useDeferredValue 会返回一个滞后的值,让昂贵子树先使用旧值,等浏览器空闲后再跟上新值。
  4. useTransition 控制“这次更新的优先级”,useDeferredValue 控制“某个值被消费的节奏”。
  5. 它们不是节流或防抖,也不会减少计算本身,只是改善更新调度和交互响应。

题目解析

这道题可以从紧急更新和非紧急更新解释。输入框 value 更新是紧急的,搜索结果列表更新可以是非紧急的。

如果渲染本身非常重,transition 只能让交互更顺滑,仍然可能需要虚拟滚动、memo 或拆分组件。

useDeferredValue 更适合不能直接控制 setState 位置的情况,例如某个 prop 变化很快但下游渲染很重。

代码示例

下面让输入值即时更新,把列表筛选结果放进 transition。

TSX
function SearchPanel({ items }: { items: Item[] }) {
  const [keyword, setKeyword] = useState('')
  const [query, setQuery] = useState('')
  const [isPending, startTransition] = useTransition()

  function handleChange(value: string) {
    setKeyword(value)
    startTransition(() => {
      setQuery(value)
    })
  }

  return (
    <>
      <input value={keyword} onChange={event => handleChange(event.target.value)} />
      {isPending ? <span>更新中</span> : null}
      <ResultList query={query} items={items} />
    </>
  )
}

常见误区

  • 把 useTransition 当防抖使用,期待它减少请求次数。
  • 重渲染根因是列表太大,却只加 transition,不做列表优化。
  • 把输入框 value 更新也放进 transition,导致输入反馈变慢。

作者信息