前端
React useTransition 深入解析
基本概念
useTransition 是一个帮助你在不阻塞 UI 的情况下更新状态的 React Hook,在React 18 中引入,它允许我们将某些更新标记为非紧急的,从而提高应用程序的响应性。
基本用法
import { useTransition } from 'react';
function MyComponent() {
/*
isPending: 表示过渡是否正在进行中。
startTransition: 包装我们想要标记为非紧急的更新.
*/
const [isPending, startTransition] = useTransition();
const handleClick = () => {
startTransition(() => {
// 在这里进行状态更新
});
};
return (
// 组件渲染逻辑
);
}
工作原理
- 当我们调用
startTransition
并传入一个回调函数时,React 会将该回调函数中的所有状态更新标记为非紧急。 - React 会先处理所有其他紧急的更新,然后再处理这些非紧急更新。
- 在过渡期间,React 可能会多次中断和恢复渲染,以确保不会阻塞主线程。
关键点
- 立即执行:传入的函数会在主线程上立即执行,这与常规函数调用并没有区别。它不会异步或推迟执行,也不会切换到其他线程上去执行。
- 调度状态更新:startTransition 内部函数执行过程中触发的状态更新,如 setState,该状态更新会被标记为 transition。
- 只影响 React 更新的优先级。
拓展: requestIdleCallback 和 web worker
useTransition 和 requestIdleCallback 都是用于优化性能的方法,但它们在工作方式和使用场景上有一些重要的区别。
startTransition
解决的是渲染阻塞的问题requestIdleCallback
适合轻量级、非紧集任务,解决主线程阻塞问题。web worker
适合处理复杂的计算任务,如大量数据处理、图像处理等,并在独立的线程中运行,避免阻塞主线程。
// 使用 requestIdleCallback 实现大量轻量级任务的调度
function performTasks(tasks) {
if (tasks.length === 0) {
return;
}
let i = 0;
function _run() {
requestIdleCallback((idle) => {
while (i < tasks.length && idle.timeRemaining() > 0) {
tasks[i++]();
}
if (i < tasks.length) {
_run();
}
})
}
_run();
}
// 创建 Web Worker
const worker = new Worker('worker.js');
// 监听 Worker 的返回消息
worker.onmessage = function(event) {
console.log('主线程接收到数据: ' + event.data);
};
// 向 Worker 发送消息
worker.postMessage('开始计算');
// 终止 Worker
// worker.terminate();
onmessage = function(event) {
console.log('Worker 接收到消息: ' + event.data);
// 执行一个复杂计算任务
let result = 0;
for (let i = 0; i < 1000000000000; i++) {
result += i;
}
// 发送计算结果回主线程
postMessage(result);
};