Skip to content

并发模式概述

第一部分:并发模式介绍

1.1 什么是并发模式

并发模式(Concurrent Mode)是React 18引入的新特性,允许React同时准备多个版本的UI,并根据优先级智能地调度更新,从而提供更流畅的用户体验。

核心特点:

  • 可中断的渲染
  • 优先级调度
  • 时间切片
  • 自动批处理
  • Suspense集成

与传统模式的对比:

javascript
// 传统模式(React 17及之前)
ReactDOM.render(<App />, document.getElementById('root'));
// - 同步渲染,不可中断
// - 一次只能准备一个UI版本
// - 长任务会阻塞主线程

// 并发模式(React 18+)
import { createRoot } from 'react-dom/client';

const root = createRoot(document.getElementById('root'));
root.render(<App />);
// - 异步渲染,可中断
// - 可同时准备多个UI版本
// - 自动时间切片,保持响应

1.2 为什么需要并发模式

传统模式的问题:

javascript
// 问题1:长任务阻塞
function HeavyList({ items }) {
  // 渲染10000个复杂项目
  return (
    <ul>
      {items.map(item => (
        <ExpensiveItem key={item.id} data={item} />
      ))}
    </ul>
  );
}

// 问题:渲染期间
// - 用户输入无响应
// - 动画卡顿
// - 页面冻结

// 问题2:无法区分优先级
function App() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  
  const handleInput = (e) => {
    setQuery(e.target.value);           // 紧急
    setResults(search(e.target.value)); // 非紧急
    // 两个更新同等优先级,都会阻塞
  };
}

// 问题3:加载状态管理复杂
function DataComponent() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    setLoading(true);
    fetch('/api/data')
      .then(res => res.json())
      .then(data => {
        setData(data);
        setLoading(false);
      })
      .catch(err => {
        setError(err);
        setLoading(false);
      });
  }, []);
  
  // 手动管理loading/error状态很繁琐
}

并发模式的解决方案:

javascript
// 解决方案1:可中断渲染
function HeavyList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <ExpensiveItem key={item.id} data={item} />
      ))}
    </ul>
  );
}
// 并发模式自动切片,保持响应

// 解决方案2:优先级调度
function App() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const [isPending, startTransition] = useTransition();
  
  const handleInput = (e) => {
    setQuery(e.target.value);  // 高优先级,立即执行
    
    startTransition(() => {
      setResults(search(e.target.value));  // 低优先级,可中断
    });
  };
}

// 解决方案3:Suspense简化加载
function DataComponent() {
  const data = use(fetchData());  // 自动suspend
  
  return <div>{data.content}</div>;
}

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <DataComponent />
    </Suspense>
  );
}

1.3 并发模式的核心概念

javascript
// 1. 可中断渲染
function interruptibleRendering() {
  // React可以:
  // - 开始渲染更新
  // - 暂停渲染
  // - 处理高优先级任务
  // - 恢复或丢弃之前的渲染
}

// 2. 时间切片
function timeSlicing() {
  // 大任务被分成5ms的小块
  while (hasWork && !shouldYield()) {
    doWork();
  }
  
  if (hasWork) {
    // 让出控制权,下一帧继续
    scheduleCallback(continueWork);
  }
}

// 3. 优先级调度
const priorities = {
  Immediate: 1,      // 同步,立即执行
  UserBlocking: 2,   // 用户交互
  Normal: 3,         // 普通更新
  Low: 4,           // 低优先级
  Idle: 5           // 空闲时执行
};

// 4. 并发特性
function concurrentFeatures() {
  // - useTransition: 标记非紧急更新
  // - useDeferredValue: 延迟更新
  // - Suspense: 声明式加载
  // - startTransition: 过渡API
}

第二部分:启用并发模式

2.1 创建并发根

javascript
// React 18之前
import ReactDOM from 'react-dom';

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

// React 18并发模式
import { createRoot } from 'react-dom/client';

const container = document.getElementById('root');
const root = createRoot(container);

root.render(<App />);

// 高级配置
const root = createRoot(container, {
  // 配置选项
  onRecoverableError: (error) => {
    console.error('Recoverable error:', error);
  },
  identifierPrefix: 'my-app'
});

root.render(<App />);

// 卸载
root.unmount();

2.2 Hydration根

javascript
// SSR应用的并发模式
import { hydrateRoot } from 'react-dom/client';

const container = document.getElementById('root');

hydrateRoot(container, <App />);

// 带配置的hydration
hydrateRoot(
  container,
  <App />,
  {
    onRecoverableError: (error, errorInfo) => {
      console.error('Hydration error:', error);
      console.log('Component stack:', errorInfo.componentStack);
    }
  }
);

// 完整的SSR设置
// server.js
import { renderToPipeableStream } from 'react-dom/server';

app.get('/', (req, res) => {
  const { pipe } = renderToPipeableStream(<App />, {
    bootstrapScripts: ['/client.js'],
    onShellReady() {
      res.setHeader('content-type', 'text/html');
      pipe(res);
    }
  });
});

// client.js
import { hydrateRoot } from 'react-dom/client';

hydrateRoot(document.getElementById('root'), <App />);

2.3 严格模式与并发

javascript
// StrictMode在并发模式下更严格
import { StrictMode } from 'react';

function App() {
  return (
    <StrictMode>
      <YourApp />
    </StrictMode>
  );
}

// StrictMode会:
// 1. 双重调用函数组件
function Component() {
  console.log('render');  // 开发环境会打印两次
  return <div>Content</div>;
}

// 2. 双重调用useEffect
function Component() {
  useEffect(() => {
    console.log('effect');  // 调用两次
    return () => {
      console.log('cleanup');  // 调用两次
    };
  }, []);
}

// 3. 检测不安全的生命周期
class OldComponent extends React.Component {
  componentWillMount() {  // 警告:不安全
    // ...
  }
}

// 4. 检测意外的副作用
function Component() {
  const ref = useRef(0);
  ref.current++;  // 警告:渲染中的副作用
  
  return <div>{ref.current}</div>;
}

2.4 迁移到并发模式

javascript
// 渐进式迁移策略

// 步骤1:更新到React 18
npm install react@18 react-dom@18

// 步骤2:更新根API
// Before
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, container);

// After
import { createRoot } from 'react-dom/client';
const root = createRoot(container);
root.render(<App />);

// 步骤3:启用StrictMode检查问题
root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

// 步骤4:逐步采用并发特性
function App() {
  // 开始使用useTransition
  const [isPending, startTransition] = useTransition();
  
  // 开始使用useDeferredValue
  const deferredValue = useDeferredValue(value);
  
  // 开始使用Suspense
  return (
    <Suspense fallback={<Loading />}>
      <AsyncComponent />
    </Suspense>
  );
}

// 步骤5:测试和优化
// - 使用Profiler监控性能
// - 检查并发相关问题
// - 优化组件渲染

第三部分:并发特性详解

3.1 useTransition

javascript
// useTransition标记非紧急更新
import { useState, useTransition } from 'react';

function SearchPage() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const [isPending, startTransition] = useTransition();
  
  const handleSearch = (value) => {
    // 紧急:立即更新输入框
    setQuery(value);
    
    // 非紧急:可中断的搜索
    startTransition(() => {
      const searchResults = performSearch(value);
      setResults(searchResults);
    });
  };
  
  return (
    <div>
      <input
        value={query}
        onChange={(e) => handleSearch(e.target.value)}
        placeholder="搜索..."
      />
      
      {isPending ? (
        <div>搜索中...</div>
      ) : (
        <SearchResults results={results} />
      )}
    </div>
  );
}

// 高级用法
function TabContainer() {
  const [tab, setTab] = useState('home');
  const [isPending, startTransition] = useTransition();
  
  const selectTab = (nextTab) => {
    startTransition(() => {
      setTab(nextTab);
    });
  };
  
  return (
    <>
      <Tabs selectedTab={tab} onSelect={selectTab} />
      {isPending && <Spinner />}
      <TabContent tab={tab} />
    </>
  );
}

// 配置超时
function Component() {
  const [isPending, startTransition] = useTransition({
    timeoutMs: 3000  // 3秒后强制提交
  });
  
  const handleAction = () => {
    startTransition(() => {
      // 如果3秒内未完成,强制显示新UI
      updateState();
    });
  };
}

3.2 useDeferredValue

javascript
// useDeferredValue延迟更新
import { useState, useDeferredValue, useMemo } from 'react';

function SearchResults() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);
  
  const results = useMemo(
    () => performSearch(deferredQuery),
    [deferredQuery]
  );
  
  return (
    <div>
      <input
        value={query}
        onChange={(e) => setQuery(e.target.value)}
      />
      
      <div className={query !== deferredQuery ? 'dimmed' : ''}>
        <Results data={results} />
      </div>
    </div>
  );
}

// 与防抖的对比
function DebounceVsDeferred() {
  const [query, setQuery] = useState('');
  
  // 防抖:固定延迟
  const debouncedQuery = useDebounce(query, 300);
  
  // useDeferredValue:智能延迟
  const deferredQuery = useDeferredValue(query);
  
  // useDeferredValue的优势:
  // 1. 自动调整延迟时间
  // 2. 高优先级更新可以打断
  // 3. 与React调度器集成
}

// 复杂场景
function FilteredList({ items }) {
  const [filter, setFilter] = useState('');
  const deferredFilter = useDeferredValue(filter);
  
  const filteredItems = useMemo(() => {
    if (!deferredFilter) return items;
    
    return items.filter(item =>
      item.name.toLowerCase().includes(deferredFilter.toLowerCase())
    );
  }, [items, deferredFilter]);
  
  const isStale = filter !== deferredFilter;
  
  return (
    <div>
      <input
        value={filter}
        onChange={(e) => setFilter(e.target.value)}
        placeholder="过滤..."
      />
      
      <div style={{ opacity: isStale ? 0.5 : 1 }}>
        <List items={filteredItems} />
      </div>
    </div>
  );
}

3.3 Suspense数据获取

javascript
// Suspense配合并发模式
import { Suspense } from 'react';

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <UserProfile />
      <Posts />
    </Suspense>
  );
}

// 使用use() Hook
function UserProfile() {
  const user = use(fetchUser());
  
  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.bio}</p>
    </div>
  );
}

// 嵌套Suspense
function App() {
  return (
    <Suspense fallback={<PageSkeleton />}>
      <Header />
      
      <Suspense fallback={<ContentSkeleton />}>
        <MainContent />
      </Suspense>
      
      <Suspense fallback={<SidebarSkeleton />}>
        <Sidebar />
      </Suspense>
    </Suspense>
  );
}

// SuspenseList(实验性)
import { SuspenseList } from 'react';

function Feed() {
  return (
    <SuspenseList revealOrder="forwards">
      <Suspense fallback={<Skeleton />}>
        <Post id={1} />
      </Suspense>
      
      <Suspense fallback={<Skeleton />}>
        <Post id={2} />
      </Suspense>
      
      <Suspense fallback={<Skeleton />}>
        <Post id={3} />
      </Suspense>
    </SuspenseList>
  );
}

3.4 自动批处理

javascript
// React 18的自动批处理
function handleClick() {
  // React 18会自动批处理,只触发一次重渲染
  setCount(c => c + 1);
  setFlag(f => !f);
  setValue(v => v * 2);
}

// 在异步代码中也会批处理
async function handleAsyncClick() {
  await fetchData();
  
  // React 18会批处理
  setData(newData);
  setLoading(false);
  setError(null);
  // 只触发一次重渲染
}

// setTimeout中也会批处理
function handleTimeout() {
  setTimeout(() => {
    // React 18会批处理
    setCount(1);
    setFlag(true);
    // 只触发一次重渲染
  }, 1000);
}

// 退出批处理
import { flushSync } from 'react-dom';

function handleClick() {
  flushSync(() => {
    setCount(c => c + 1);
  });
  // DOM已更新
  
  flushSync(() => {
    setFlag(f => !f);
  });
  // DOM已更新
  
  // 触发了两次重渲染
}

// React 17 vs React 18
// React 17
function handleClick() {
  setCount(c => c + 1);  // 重渲染
  setFlag(f => !f);      // 重渲染
  // 总共2次重渲染
}

// React 18
function handleClick() {
  setCount(c => c + 1);
  setFlag(f => !f);
  // 总共1次重渲染
}

第四部分:并发模式最佳实践

4.1 何时使用并发特性

javascript
// 场景1:实时搜索/过滤
function SearchPage() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const [isPending, startTransition] = useTransition();
  
  const handleSearch = (value) => {
    setQuery(value);
    
    startTransition(() => {
      // 大量数据的搜索
      setResults(heavySearch(value));
    });
  };
  
  return (
    <>
      <SearchInput value={query} onChange={handleSearch} />
      {isPending && <SearchingIndicator />}
      <Results data={results} />
    </>
  );
}

// 场景2:Tab切换
function TabPanel() {
  const [tab, setTab] = useState('overview');
  const [isPending, startTransition] = useTransition();
  
  const switchTab = (newTab) => {
    startTransition(() => {
      setTab(newTab);
      // 预加载Tab数据
      prefetchTabData(newTab);
    });
  };
  
  return (
    <>
      <TabBar activeTab={tab} onSwitch={switchTab} />
      {isPending && <LoadingBar />}
      <TabContent tab={tab} />
    </>
  );
}

// 场景3:数据可视化
function Chart({ data }) {
  const [filter, setFilter] = useState('all');
  const deferredFilter = useDeferredValue(filter);
  
  const chartData = useMemo(
    () => processChartData(data, deferredFilter),
    [data, deferredFilter]
  );
  
  return (
    <>
      <FilterControls value={filter} onChange={setFilter} />
      <ComplexChart
        data={chartData}
        isStale={filter !== deferredFilter}
      />
    </>
  );
}

// 场景4:无限滚动
function InfiniteList() {
  const [items, setItems] = useState([]);
  const [isPending, startTransition] = useTransition();
  
  const loadMore = () => {
    startTransition(() => {
      fetchNextPage().then(newItems => {
        setItems(prev => [...prev, ...newItems]);
      });
    });
  };
  
  return (
    <>
      <List items={items} />
      {isPending && <LoadingMore />}
      <button onClick={loadMore}>Load More</button>
    </>
  );
}

4.2 性能优化策略

javascript
// 1. 合理使用memo
const ExpensiveComponent = memo(function ExpensiveComponent({ data }) {
  // 只有data变化时才重渲染
  return <div>{processData(data)}</div>;
});

function Parent() {
  const [count, setCount] = useState(0);
  const [data] = useState(heavyData);
  
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>
        Count: {count}
      </button>
      {/* data没变,不会重渲染 */}
      <ExpensiveComponent data={data} />
    </div>
  );
}

// 2. 优化Transition边界
function OptimizedApp() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const [isPending, startTransition] = useTransition();
  
  // ✅ 只包裹耗时操作
  const handleSearch = (value) => {
    setQuery(value);  // 立即执行
    
    startTransition(() => {
      setResults(search(value));  // 可中断
    });
  };
  
  // ❌ 不要包裹所有更新
  const badSearch = (value) => {
    startTransition(() => {
      setQuery(value);  // 不应该在transition中
      setResults(search(value));
    });
  };
}

// 3. 使用Suspense边界
function App() {
  return (
    // ✅ 合理的Suspense粒度
    <div>
      <Header />
      
      <Suspense fallback={<MainSkeleton />}>
        <MainContent />
      </Suspense>
      
      <Suspense fallback={<SidebarSkeleton />}>
        <Sidebar />
      </Suspense>
    </div>
  );
  
  // ❌ 太粗的粒度
  // <Suspense fallback={<PageSkeleton />}>
  //   <EntireApp />
  // </Suspense>
}

// 4. 预加载策略
function PreloadStrategy() {
  const [tab, setTab] = useState('home');
  
  const handleTabHover = (nextTab) => {
    // 鼠标悬停时预加载
    startTransition(() => {
      preloadTabData(nextTab);
    });
  };
  
  const handleTabClick = (nextTab) => {
    setTab(nextTab);
  };
  
  return (
    <Tabs
      activeTab={tab}
      onTabHover={handleTabHover}
      onTabClick={handleTabClick}
    />
  );
}

4.3 错误处理

javascript
// 并发模式下的错误边界
class ConcurrentErrorBoundary extends React.Component {
  state = { hasError: false, error: null };
  
  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }
  
  componentDidCatch(error, errorInfo) {
    // 并发渲染中的错误
    console.error('Concurrent render error:', error);
    logErrorToService(error, errorInfo);
  }
  
  render() {
    if (this.state.hasError) {
      return <ErrorFallback error={this.state.error} />;
    }
    
    return this.props.children;
  }
}

// 使用
function App() {
  return (
    <ConcurrentErrorBoundary>
      <Suspense fallback={<Loading />}>
        <AsyncComponent />
      </Suspense>
    </ConcurrentErrorBoundary>
  );
}

// 处理Transition错误
function Component() {
  const [isPending, startTransition] = useTransition();
  const [error, setError] = useState(null);
  
  const handleAction = () => {
    setError(null);
    
    startTransition(() => {
      try {
        performAction();
      } catch (err) {
        setError(err);
      }
    });
  };
  
  if (error) {
    return <ErrorMessage error={error} />;
  }
  
  return (
    <button onClick={handleAction} disabled={isPending}>
      {isPending ? 'Loading...' : 'Action'}
    </button>
  );
}

4.4 测试并发组件

javascript
// 测试Transition
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('handles transition updates', async () => {
  render(<SearchComponent />);
  
  const input = screen.getByRole('textbox');
  
  // 输入查询
  await userEvent.type(input, 'react');
  
  // 等待transition完成
  await waitFor(() => {
    expect(screen.getByText(/搜索中/)).toBeInTheDocument();
  });
  
  await waitFor(() => {
    expect(screen.getByText(/results/i)).toBeInTheDocument();
  });
});

// 测试Suspense
test('shows loading state', async () => {
  render(
    <Suspense fallback={<div>Loading...</div>}>
      <AsyncComponent />
    </Suspense>
  );
  
  // 应该显示loading
  expect(screen.getByText('Loading...')).toBeInTheDocument();
  
  // 等待数据加载
  await waitFor(() => {
    expect(screen.getByText('Content')).toBeInTheDocument();
  });
});

// 测试并发渲染
import { act } from '@testing-library/react';

test('concurrent rendering', async () => {
  const { rerender } = render(<App count={0} />);
  
  // 使用act包裹并发更新
  await act(async () => {
    rerender(<App count={1} />);
    rerender(<App count={2} />);
  });
  
  expect(screen.getByText('2')).toBeInTheDocument();
});

第五部分:性能监控

5.1 Profiler API

javascript
// 监控并发渲染性能
import { Profiler } from 'react';

function App() {
  const onRenderCallback = (
    id,
    phase,
    actualDuration,
    baseDuration,
    startTime,
    commitTime
  ) => {
    console.log('Profiler:', {
      id,
      phase,
      actualDuration,
      baseDuration,
      efficiency: (baseDuration / actualDuration * 100).toFixed(2) + '%'
    });
  };
  
  return (
    <Profiler id="App" onRender={onRenderCallback}>
      <Profiler id="Search" onRender={onRenderCallback}>
        <SearchComponent />
      </Profiler>
      
      <Profiler id="Results" onRender={onRenderCallback}>
        <ResultsComponent />
      </Profiler>
    </Profiler>
  );
}

// 检测Transition性能
function TransitionProfiler() {
  const [isPending, startTransition] = useTransition();
  const startTimeRef = useRef(null);
  
  const handleAction = () => {
    startTimeRef.current = performance.now();
    
    startTransition(() => {
      performAction();
      
      const duration = performance.now() - startTimeRef.current;
      console.log('Transition duration:', duration);
      
      if (duration > 100) {
        console.warn('Slow transition:', duration);
      }
    });
  };
}

5.2 DevTools使用

javascript
// React DevTools标记
import { unstable_trace as trace } from 'scheduler/tracing';

function Component() {
  const handleAction = () => {
    trace('User Action', performance.now(), () => {
      // 这个操作会在DevTools中标记
      performAction();
    });
  };
  
  return <button onClick={handleAction}>Action</button>;
}

// Concurrent特性追踪
function DebugConcurrent() {
  const [isPending, startTransition] = useTransition();
  
  useEffect(() => {
    if (isPending) {
      console.log('Transition started');
    } else {
      console.log('Transition completed');
    }
  }, [isPending]);
}

5.3 性能指标收集

javascript
// 收集并发模式性能数据
class ConcurrentMetrics {
  constructor() {
    this.metrics = {
      transitions: [],
      suspensions: [],
      renders: []
    };
  }
  
  recordTransition(id, duration) {
    this.metrics.transitions.push({
      id,
      duration,
      timestamp: Date.now()
    });
  }
  
  recordSuspension(component, duration) {
    this.metrics.suspensions.push({
      component,
      duration,
      timestamp: Date.now()
    });
  }
  
  recordRender(component, phase, duration) {
    this.metrics.renders.push({
      component,
      phase,
      duration,
      timestamp: Date.now()
    });
  }
  
  getReport() {
    return {
      avgTransitionTime: this.average(this.metrics.transitions.map(t => t.duration)),
      avgSuspensionTime: this.average(this.metrics.suspensions.map(s => s.duration)),
      avgRenderTime: this.average(this.metrics.renders.map(r => r.duration)),
      totalTransitions: this.metrics.transitions.length,
      totalSuspensions: this.metrics.suspensions.length
    };
  }
  
  average(arr) {
    return arr.length > 0
      ? arr.reduce((a, b) => a + b, 0) / arr.length
      : 0;
  }
}

const metrics = new ConcurrentMetrics();

// 使用
function MonitoredComponent() {
  const [isPending, startTransition] = useTransition();
  const startRef = useRef(null);
  
  useEffect(() => {
    if (isPending) {
      startRef.current = performance.now();
    } else if (startRef.current) {
      const duration = performance.now() - startRef.current;
      metrics.recordTransition('action', duration);
    }
  }, [isPending]);
}

注意事项

1. 兼容性考虑

浏览器兼容性:
- 现代浏览器完全支持
- IE需要polyfill
- 移动浏览器性能差异大

React版本:
- 需要React 18+
- 某些特性仍在实验阶段

2. 常见陷阱

javascript
// ❌ 不要在Transition中读取ref
function Bad() {
  const ref = useRef();
  const [isPending, startTransition] = useTransition();
  
  const handleClick = () => {
    startTransition(() => {
      const value = ref.current.value;  // 可能不准确
      setState(value);
    });
  };
}

// ✅ 在Transition外读取
function Good() {
  const ref = useRef();
  const [isPending, startTransition] = useTransition();
  
  const handleClick = () => {
    const value = ref.current.value;  // 正确
    
    startTransition(() => {
      setState(value);
    });
  };
}

// ❌ 不要滥用Transition
function Bad() {
  const [count, setCount] = useState(0);
  
  startTransition(() => {
    setCount(count + 1);  // 简单更新不需要transition
  });
}

// ✅ 只用于耗时操作
function Good() {
  const [data, setData] = useState([]);
  
  startTransition(() => {
    setData(processLargeDataset());  // 合适
  });
}

3. 性能建议

javascript
// 1. 避免过度使用并发特性
// 2. 合理设置Suspense边界
// 3. 监控并发性能
// 4. 测试不同设备
// 5. 渐进式采用

常见问题

Q1: 并发模式会自动提升性能吗?

A: 不会。需要正确使用Transition、Suspense等特性才能看到性能提升。

Q2: 所有应用都应该用并发模式吗?

A: 不一定。简单应用可能看不到明显收益。复杂、交互频繁的应用受益最大。

Q3: 如何判断是否需要使用Transition?

A: 当更新耗时超过100ms且不是用户直接交互时,考虑使用Transition。

Q4: useDeferredValue和防抖的区别?

A: useDeferredValue智能延迟,与React调度集成;防抖固定延迟,独立于React。

Q5: Suspense只能用于数据获取吗?

A: 不是。任何异步操作都可以,如代码分割、图片加载等。

Q6: 并发模式会破坏现有代码吗?

A: 大部分不会。但StrictMode会更严格,可能暴露潜在问题。

Q7: 如何测试并发特性?

A: 使用React Testing Library,配合act()和waitFor()。

Q8: 并发模式的内存开销大吗?

A: 有一定开销(双缓冲),但优化后影响不大。

Q9: 可以选择性使用并发特性吗?

A: 可以。创建Root后,可以选择在哪些组件使用Transition等特性。

Q10: React 19对并发模式有什么改进?

A: 更稳定的API、更好的性能、更多的并发特性。

总结

核心要点

1. 并发模式基础
   ✅ 可中断渲染
   ✅ 优先级调度
   ✅ 时间切片
   ✅ 自动批处理

2. 核心特性
   ✅ useTransition
   ✅ useDeferredValue
   ✅ Suspense
   ✅ 自动批处理

3. 最佳实践
   ✅ 合理使用Transition
   ✅ 优化Suspense边界
   ✅ 性能监控
   ✅ 错误处理

4. 注意事项
   ✅ 渐进式采用
   ✅ 测试充分
   ✅ 监控性能
   ✅ 处理兼容性

实践建议

1. 从简单场景开始
2. 监控性能指标
3. 逐步优化
4. 团队培训
5. 持续改进

并发模式是React的重要进化,合理使用可以显著提升用户体验。