Q13 · React / Vue 优化
React useTransition 在实际工程中的优化作用?如何落地?
⚡ 速记答案(30 秒)
- 作用:把"紧急更新"(输入、点击)和"非紧急更新"(列表过滤、重排布局)区分开
- 使用:
const [isPending, startTransition] = useTransition(); - 紧急更新直接 setState;重计算/大渲染放在
startTransition(() => setState(...))里 - 落地场景:搜索框输入 → 结果列表过滤;复杂筛选面板、图表联动;表单编辑 + 大表格刷新
📖 详细讲解
useTransition 原理
React 18 引入的 Concurrent 特性,允许将状态更新标记为"非紧急":
• 紧急更新:立即响应用户输入
• 非紧急更新:可被打断,让位给紧急更新
使用场景
1. 搜索过滤
用户输入 → 立即显示输入内容 → 延迟更新搜索结果
2. Tab 切换
点击 Tab → 立即高亮 Tab → 延迟加载内容
3. 大列表更新
筛选条件变化 → 立即显示筛选状态 → 延迟更新列表
与 useDeferredValue 对比
| Hook | 用途 |
|---|---|
| useTransition | 控制状态更新的优先级 |
| useDeferredValue | 延迟某个值的更新 |
💻 代码示例
useTransition 实战示例
import { useState, useTransition, useMemo } from 'react';
function ProductList({ products }: { products: Product[] }) {
const [query, setQuery] = useState('');
const [isPending, startTransition] = useTransition();
// 模拟大量数据过滤
const filteredProducts = useMemo(() => {
return products.filter(p =>
p.name.toLowerCase().includes(query.toLowerCase())
);
}, [products, query]);
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
// 紧急:输入框立即响应
setQuery(value);
// 这里不需要 startTransition,因为 query 变化会自动触发 filteredProducts 重算
// 但如果是两个独立状态,可以这样用:
// startTransition(() => {
// setFilteredProducts(filterProducts(value));
// });
};
return (
<div>
<input
value={query}
onChange={handleSearch}
placeholder="搜索商品..."
/>
{isPending && <div className="loading">更新中...</div>}
<ul style={{ opacity: isPending ? 0.7 : 1 }}>
{filteredProducts.map(p => (
<li key={p.id}>{p.name}</li>
))}
</ul>
</div>
);
}面试技巧:回答性能问题时,先说指标和标准,再讲优化手段,最后结合实际项目经验。