React startTransition使用
startTransition
React 18 引入的 API,用于将某些状态更新标记为低优先级的过渡更新(Transition),与高优先级的紧急更新区分开来。
核心概念
React 将更新分为两类:
| 类型 | 例子 | 优先级 |
|---|---|---|
| 紧急更新 | 输入框打字、按钮点击、滚动 | 高,立即响应 |
| 过渡更新 | 搜索结果渲染、页面切换、图片加载后的 UI 变化 | 低,可被中断 |
行为特性
1. 可中断性
过渡更新可以被新的紧急更新打断。比如用户在搜索时继续打字,React 会放弃上一次过渡渲染,优先处理新的输入。
2. 不会阻塞 UI
紧急更新始终优先执行,过渡更新在空闲时处理,页面不会卡顿。
3. 批量合并
startTransition 内的多个 setState 会被合并为一次渲染。
使用方式
import { startTransition } from "react";
// 方式一:直接调用(无 isPending 状态)
startTransition(() => {
setTab("settings");
setData(newData);
});
// 方式二:useTransition hook(可获取 pending 状态)
const [isPending, startTransition] = useTransition();
startTransition(() => {
setTab("settings");
});
// isPending 为 true 时可显示 loading 指示器
{
isPending && <Spinner />;
}
在你的代码中的作用
SmartAvatar 的 useEffect 里同步调用 setState 会触发级联渲染警告。用 startTransition 包裹后:
useEffect(() => {
if (!target) {
startTransition(() => setLoaded(false)); // 标记为低优先级
return;
}
// ...
}, [target]);
React 将这些状态变更视为过渡更新,不会在 effect 执行阶段立即触发同步重渲,从而消除级联渲染问题。
与 useDeferredValue 的区别
startTransition |
useDeferredValue |
|
|---|---|---|
| 控制对象 | 状态更新 的优先级 | 值 的更新延迟 |
| 使用场景 | 你控制 setState 的地方 | 你接收 props/state 但无法控制其来源 |
