useTransition Hook 的作用及使用场景
在 React 18 中,引入了并发模式(Concurrent Mode)相关的新特性,useTransition 就是其中之一。这是一个用于优化用户交互体验的 Hook,它允许你将某些状态更新标记为非阻塞式的,从而保持 UI 的响应性。
一、useTransition 的作用
useTransition 的主要作用是:
将一个状态更新标记为“过渡”(transition),告诉 React 这个更新不是紧急的,可以延后处理,以便优先处理更紧急的任务(如用户输入、动画等)。
语法:
jsx
const [isPending, startTransition] = useTransition();
- isPending:布尔值,表示 transition 是否仍在进行中。
- startTransition(callback):接收一个回调函数,其中放置你想要延迟执行的状态更新逻辑。
二、使用场景
- 大数据渲染或复杂计算时保持页面响应
当组件需要进行大规模数据渲染或耗时计算时,直接更新状态可能会导致页面卡顿。此时可以使用 useTransition 将非紧急的状态更新推迟处理。
示例:
jsx
import { useState, useTransition } from 'react';
function BigList({ input }) {
const [list, setList] = useState([]);
const [isPending, startTransition] = useTransition();
const handleInputChange = (e) => {
const value = e.target.value;
// 紧急任务:立即更新输入框内容
// ...
// 非紧急任务:延迟过滤/渲染列表
startTransition(() => {
const newList = filterData(value); // Assume heavy computation here
setList(newList);
});
};
return (
<>
<input onChange={handleInputChange} />
{isPending && <p>Loading...</p>}
<ul>
{list.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
</>
);
}
- Tab切换、路由跳转等不要求即时完成的UI变更
例如实现标签页切换时避免界面卡顿:
jsx
const [tab, setTab] = useState('home');
const [isPending, startTransition] = useTransition();
function selectTab(nextTab) {
startTransition(() => {
setTab(nextTab); // tab切换可以稍后完成以优先响应用户输入
});
}
- UI展示需要等待数据加载时的平滑过渡效果
比如根据搜索词请求后端接口并展示结果:
jsx
startTransition(() => {
setSearchResult(data);
});
三、注意事项
- useTransition仅在 React 18+中支持;
- transition中的状态改变不会打断用户的输入;相比 setTimeout,它具有更好的优先级调度能力;
- isPending可以用于显示loading提示提升用户体验;
- useDeferredValue也可以达到类似目的(从另一个角度解决同一问题)。
四、与 setTimeout / debounce / throttle的区别
| 方法 | 特点 |
|---|---|
| setTimeout | setTimeout只是简单延时执行代码块,不具备React调度机制 |
| debounce/throttle | 常用于限制高频触发事件频率(如搜索框联想),但无法区分“优先级” |
| useTransition | React内部基于优先级调度的机制控制状态更新的顺序和中断行为 |
五、总结
✅ 适用场景:
- UI需要保持高响应性的场合;
- state变化导致大量子组件重渲染或耗时计算;
- “不那么紧急”的状态变更可与用户交互并行发生;
🚫 不适用场景:
- state必须立即生效的场景(如表单验证);
- state很小且不会导致性能瓶颈的情况;
通过使用 useTransition,可以让你的应用在繁重操作中依然保持流畅的交互体验。