标准答案
- useTransition 返回 isPending 和 startTransition,可以把一组更新标记为低优先级。
- 适合场景是用户输入或点击要立即响应,但由它触发的大列表渲染、路由切换或重计算可以延后。
- useDeferredValue 会返回一个滞后的值,让昂贵子树先使用旧值,等浏览器空闲后再跟上新值。
- useTransition 控制“这次更新的优先级”,useDeferredValue 控制“某个值被消费的节奏”。
- 它们不是节流或防抖,也不会减少计算本身,只是改善更新调度和交互响应。
题目解析
这道题可以从紧急更新和非紧急更新解释。输入框 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,导致输入反馈变慢。