什么是Transition
Transition 为使用者提供设置更新任务等级的接口,可以通过Transition实现提升用户体验的优雅过度效果。在React18中引入的新的API,包括startTransition和useTransition,这些API为处理UI更新提供了更加优雅的处理方式,特别是在处理一些耗时操作时能显著提升性能,其目的是让耗时更新能够不影响用户的页面交互。
Transition的工作机制是将更新标记为低优先级任务,React会在浏览器空闲时执行被标记的更新任务。如果插入紧急(高优先级)任务,React会中断Transition,执行高优先级任务后在恢复Transition的执行,这依赖于React内部的任务调度机制。基于这种机制,React能够避免阻塞紧急更新的渲染。
紧急任务:直接影响用户交互的操作,如按键、输入、点击等。
非紧急任务:不影响用户交互的操作,如搜索结果的展示、列表过滤、UI状态的切换等
为什么需要Transition
在React18之前,所有的更新任务都被视为紧急更新任务,当有大量数据处理或者复杂计算时,这些更新可能会阻塞UI,导致页面卡顿。Transition通过降低更新任务的优先级为我们提供了更好的并发控制,解决更新的性能问题和用户体验
基本使用
useTransition 是一个hook,不接受任何参数,返回更新处理状态pending和startTransition函数,startTransition函数和startTransition API作用是一样的。
startTransition函数接收一个action函数,action函数内部调用set(组件内部的set)会被标记为非紧急更新任务,action会立即执行。
import { useState, useTransition } from 'react';
function SearchComponent() {
const [isPending, startTransition] = useTransition();
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const handleChange = (e) => {
const value = e.target.value;
setQuery(value);
// 将搜索操作标记为非紧急更新
startTransition(() => {
// 模拟耗时的搜索操作
const filteredResults = performSearch(value);
setResults(filteredResults);
});
};
return (
<div>
<input
value={query}
onChange={handleChange}
placeholder="输入搜索关键词"
/>
{isPending ? (
<div>搜索中...</div>
) : (
<ul>
{results.map(result => (
<li key={result.id}>{result.name}</li>
))}
</ul>
)}
</div>
);
}
在使用Transition时需要注意以下几点:
- setTimeout内部的set不会被标记。
- 不会标记prop或者自定义Hook的set。
- 同一个startTranstion不会标记到await之后的set。
- 正确的区分紧急更新和非紧急更新。
- transition更新不会触发Suspense预设UI。