在 React 18 版本中,引入了 并发更新(Concurrent Rendering) 的概念,这是一种新的渲染模式,允许 React 更加智能地协调 UI 更新,提高应用的流畅度和响应速度。
一. 什么是并发更新?
并发更新(Concurrent Rendering) 允许 React 中断和恢复渲染 ,并根据用户的交互优先级调整渲染顺序。
换句话说,React 18 让渲染变得 非阻塞,不会因为某个状态更新导致整个 UI 卡顿。
在 React 17 及之前,状态更新是 同步的 ,一旦开始渲染就必须完成,无法被中断。
React 18 通过 Concurrent Mode 让状态更新变得可中断、可恢复,提高了流畅度。
二. React 18 如何实现并发更新?
React 18 通过以下机制实现 并发更新:
(1) startTransition
低优先级更新
startTransition
允许你将某些更新标记为 "可中断的" ,让 React 先处理 高优先级任务(如输入框输入) ,再异步处理低优先级的 UI 变更。
示例:
javascript
jsx
复制编辑
import { useState, startTransition } from 'react';
function App() {
const [query, setQuery] = useState('');
const [list, setList] = useState([]);
function handleChange(e) {
const value = e.target.value;
setQuery(value);
// 将列表更新标记为低优先级(异步执行)
startTransition(() => {
setList(Array.from({ length: 10000 }, (_, i) => `${value} - ${i}`));
});
}
return (
<div>
<input value={query} onChange={handleChange} placeholder="输入查询..." />
<ul>
{list.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
🔹 解析:
- 输入框的
setQuery(value)
是高优先级,React 会立刻更新它。 - 列表的
setList([...])
是低优先级,React 会延迟渲染,确保用户输入不卡顿。
效果: 即使数据量很大,输入框不会卡顿,而列表更新稍后再执行。
(2) useDeferredValue
处理 UI 延迟
useDeferredValue
允许你让某些 UI 滞后渲染,避免主线程阻塞。
示例:
javascript
jsx
复制编辑
import { useState, useDeferredValue } from 'react';
function App() {
const [text, setText] = useState('');
const deferredText = useDeferredValue(text); // 延迟更新
return (
<div>
<input value={text} onChange={(e) => setText(e.target.value)} />
<p>立即更新:{text}</p>
<p>滞后更新:{deferredText}</p>
</div>
);
}
🔹 解析:
text
会 立即更新。deferredText
会 延迟更新,减少 UI 抖动,提高性能。
(3) React 18 自动批处理
在 React 18 之前,多个 setState
在事件处理函数内会被合并 ,但如果是异步操作(如 setTimeout
),setState
仍然会触发多次渲染。
React 18 让所有状态更新自动批处理,不管同步还是异步!
javascript
jsx
复制编辑
import { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
function handleClick() {
setTimeout(() => {
setCount((prev) => prev + 1);
setText('更新完成');
}, 1000);
}
return (
<div>
<p>Count: {count}</p>
<p>Text: {text}</p>
<button onClick={handleClick}>更新</button>
</div>
);
}
🔹 React 18 之前:
setCount
触发一次渲染setText
触发第二次渲染
🔹 React 18 之后:
- 批处理 所有
setState
,只触发 一次 渲染,提高性能。
(4) useTransition
控制 UI 更新优先级
useTransition
允许你手动标记某些状态更新为 低优先级 ,类似 startTransition
。
示例:
javascript
jsx
复制编辑
import { useState, useTransition } from 'react';
function App() {
const [count, setCount] = useState(0);
const [isPending, startTransition] = useTransition();
function handleClick() {
startTransition(() => {
setCount((prev) => prev + 1);
});
}
return (
<div>
<p>Count: {count}</p>
{isPending && <p>加载中...</p>}
<button onClick={handleClick}>增加</button>
</div>
);
}
🔹 解析:
startTransition
让setCount
变成 低优先级 任务,避免影响其他 UI 操作。isPending
可以用来 显示加载状态。
三. 并发更新的应用场景
- 输入框不阻塞大列表更新 (
startTransition
) - UI 延迟更新,避免卡顿 (
useDeferredValue
) - 自动批处理,减少渲染次数(React 18 默认行为)
- 优化渲染优先级,提升交互体验 (
useTransition
)
四. 并发更新会影响现有项目吗?
不会!React 18 默认仍然是同步模式 ,但你可以选择使用 startTransition
和 useTransition
来利用并发模式。
你可以逐步引入这些特性,无需大改代码!
五. 总结
React 18 并发特性 | 作用 | 适用场景 |
---|---|---|
startTransition |
低优先级更新 | 避免输入框卡顿 |
useDeferredValue |
延迟 UI 渲染 | 文字、搜索列表 |
useTransition |
手动控制优先级 | 渲染大量数据 |
自动批处理 | 减少渲染次数 | 任何 setState |
React 18 并发模式的核心目标是:
- 让 UI 渲染更流畅
- 让状态更新更智能
- 减少不必要的重渲染
希望这些示例能帮你更好地理解 React 18 并发更新!