Q13 · React / Vue 优化

React useTransition 在实际工程中的优化作用?如何落地?

ReactuseTransitionConcurrent

⚡ 速记答案(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>
  );
}
💡
面试技巧:回答性能问题时,先说指标和标准,再讲优化手段,最后结合实际项目经验。