React 的“可中断(interruptible)”渲染,指的是 React 在执行渲染过程中可以暂停、中断、再继续或放弃更新。这是 React 18 引入的并发特性的一部分,目的是让界面响应更流畅,防止“卡顿”。
📖 举个例子:传统 vs 可中断
✅ 传统(同步)渲染
当你更新一个组件(比如 setState),React 会一口气渲染完所有内容,期间浏览器不能响应用户操作。
问题:如果这个更新很大,比如更新 5000 个列表项,界面可能卡死几百毫秒,用户点击无响应。
✅ 可中断渲染(React 18 并发模式)
React 会:
-
把渲染分为多个小任务。
-
每执行一小段逻辑,就“让一让”给浏览器,比如让它响应滚动、输入、点击。
-
如果你中途发起了更重要的更新(如点击按钮),它甚至可以打断当前渲染并优先处理更紧急的事。
这就是“可中断”的意义。
🔧 怎么启用“可中断”?
React 18 开始,默认的渲染是同步的,要用 createRoot()
才能进入并发模式(可中断):
// React 18
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<App />);
旧写法(ReactDOM.render)是不支持并发、不可中断的。
🧠 底层原理(简单了解下)
React 18 使用了所谓的Fiber 架构,它本质上是把渲染任务切成小块(Fiber 节点),然后用 requestIdleCallback
或 scheduler
在浏览器空闲时间执行这些任务。
可中断意味着:
-
React 可以暂停某个组件树的渲染。
-
React 可以放弃某个渲染(比如新来了更重要的 setState)。
-
React 可以重新调度优先级更高的任务。
🚀 应用场景举例
1. 大数据渲染
import React, { useState, startTransition } from 'react';
import { createRoot } from 'react-dom/client';
const App = () => {
const [list, setList] = useState([]);
const [loading, setLoading] = useState(false);
// 同步加载(不可中断)
const handleSyncLoad = () => {
setLoading(true);
const data = Array.from({ length: 10000 }, (_, i) => `同步项 ${i}`);
setList(data);
setLoading(false);
};
// 可中断加载(使用并发 startTransition)
const handleAsyncLoad = () => {
setLoading(true);
const data = Array.from({ length: 10000 }, (_, i) => `可中断项 ${i}`);
startTransition(() => {
setList(data);
setLoading(false);
});
};
return (
<div style={{ padding: 20 }}>
<h2>React 可中断渲染演示</h2>
<button onClick={handleSyncLoad}>同步加载数据(会卡)</button>
<button onClick={handleAsyncLoad} style={{ marginLeft: 10 }}>可中断加载(更流畅)</button>
{loading && <p>加载中...</p>}
<ul>
{list.map((item, i) => (
<li key={i}>{item}</li>
))}
</ul>
</div>
);
};
const root = createRoot(document.getElementById('root'));
root.render(<App />);
使用可中断渲染 + 虚拟滚动技术可以防止页面卡顿。
2. 用户打字中,setState 不应卡住输入
你在输入框输入时,如果某些组件更新太慢,React 可中断那些不重要的更新,保证输入流畅。
✅ 总结一句话:
React 的“可中断渲染”就是让 UI 更新更聪明地调度:重要的先处理、不重要的先等会儿,有空再干。