Transition 使用姿势
Transition 是 react18 引入的新概念,用来区分紧急和非紧急的更新。
- 紧急的更新,指的是一些直接的用户交互,如输入、点击等;
- 非紧急的更新,指的是 UI 界面从一个样子过渡到另一个样子;
react 官方的 demo 如下:
import {
startTransition} from 'react';
// Urgent: Show what was typed
setInputValue(input);
// Mark any state updates inside as transitions
startTransition(() => {
// Transition: Show the results
setSearchQuery(input);
});
有 2 个 API:
- useTransition:hook,用在 function 组件或其他 hooks 中,能返回 isPending;
- startTransition:用在不能使用 hooks 的场景,如 class 组件中,相比 useTransition 不能获取 isPending 状态;
2 个 API 还有一个差别:当进行连续快速输入时,使用 startTransition 是无法触发类似 throttle 的效果的。
Transition VS throttle、debounce
存在的问题:
- 到达指定时间后,更新开始处理,渲染引擎会被长时间阻塞,页面交互会出现卡顿;
- throttle 的最佳时间不易掌握,是由开发者设置的时间。而这个预设的时间,在不同性能的设备上不一定能带来最佳的体验;
存在的问题:
- 会出现用户输入长时间得不到响应的情况,如上例中虽然输入框中内容一直在变但下面区域内一直不变;
- 更新操作正式开始以后,渲染引擎仍然会被长时间阻塞,依旧会存在页面卡死的情况;
用 transition 机制的效果:
- 用户可以及时看到输入内容,交互也较流畅;
- 用户连续输入时,不会一直得不到响应(最迟 5s 必会开始更新渲染列表);
- 开始更新渲染后,协调过程是可中断的,不会长时间阻塞渲染引擎(进入浏览器渲染阶段依然会卡住);
transition 相比前两种方案的优势:
- 更新协调过程是可中断的,渲染引擎不会长时间被阻塞,用户可以及时得到响应;
- 不需要开发人员去做额外的考虑,整个优化过程交给 react 和浏览器即可;
transition 实现原理
isPending 实现原理
我们看到页面首先进入了 pending 状态,然后才显示为 transition 更新后的结果。这里发生了 2 次 react 更新。但我们只写了一个 setState。
function App() {
const [value, setValue] = useState("");
const [isPending, startTransition] = useTransition();
const handleChange = (e) => {
const newVal = e.target.value;
startTransition(() => setValue(newVal));
};
return (
<div>
<input onChange={
handleChange} />
<div className={
isPending ? 'loading' : ''}>
{
Array(50000).fill("a").map((item, index) => {
return <div key={
index}>{
value}</div>;
})
}
</div>
</div>
);
}
我们看一下 useTransition 源码:
useTransition