React 18 之前,一次 reconciliation 一旦开始就必须同步完成,数据量大的更新会长时间占住主线程,输入框敲字、动画都会明显卡顿。并发的核心是 Fiber 架构把渲染拆成可暂停的工作单元:高优先级更新(用户输入)可以打断低优先级更新先渲染,之后低优先级任务再基于最新状态重来。
对开发者最直接的相关 API 是 startTransition 与 useDeferredValue,标记哪些更新可以慢一点;Suspense 在并发模式下才真正成为一等公民,配合 lazy 做到数据到了再渲染。需要注意:并发不是多线程,也不让全部场景变快,它只在存在可降优先级的更新时才有收益。
import { startTransition, useState, useDeferredValue, useMemo } from 'react'; function Search() { const [text, setText] = useState(''); // 高优先级:输入立即响应 const [query, setQuery] = useState(''); // 低优先级:可被高优先级打断 const deferred = useDeferredValue(query); // 列表再慢半拍也无妨 const list = useMemo( () => bigData.filter((s) => s.includes(deferred)), [ deferred ] ); return ( <> <input value={text} onChange={(e) => { setText(e.target.value); // 输入框立刻更新 startTransition(() => { setQuery(e.target.value); }); // 列表降级为过渡 }} /> <ul>{list.slice(0, 50).map((s) => <li key={s}>{s}</li>)}</ul> </> ); }