跳到主要内容

认识

2023年12月20日
柏拉文
越努力,越幸运

一、认识


useTransition 用于在 createRoot 开启的并发特性模式下, 开启并发渲染。主要解决浏览器执行大量渲染工作问题时的卡顿问题。useTransition 返回一个数组, 第一个元素为 isPending, 表示当处于过渡状态的标志; 第二个是 startTransition , 一个方法, 里面的更新任务都会被标记成 过渡更新任务,过渡更新任务在渲染并发场景下,会被降级更新优先级,中断更新, 所以它不会让页面卡顿,React 让这些任务,在浏览器空闲时间执行。

二、语法


import { useTransition } from 'react';

function TabContainer() {
const [value, setValue] = useState(0);
const [isPending, startTransition] = useTransition();

const handleClick = ()=>{
startTransition(()=>{
setValue(1);
});
}

return <div>
{ isPending && <span>isTransition</span>}

<button onClick={handleClick}></button>

<div>{ value }</div>
</div>
}
  • isPending: 告诉你是否存在待处理的 transition

  • startTransition: 可以使用此方法将状态更新标记为 transition

三、问题


3.1 useTransition 实现原理?

3.2 useTransition vs useDeferredValue?

useDeferredValue 本质上和内部实现与 useTransition 一样都是标记成了过渡更新任务。但是, useTransition 是把 startTransition 内部的更新任务变成了过渡任务 transition,而 useDeferredValue 是把原值通过过渡任务得到新的值,这个值作为延时状态。 一个是处理一段逻辑,另一个是生产一个新的状态useDeferredValue 还有一个不同点就是这个任务,本质上在 useEffect 内部执行,而 useEffect 内部逻辑是异步执行的 ,所以它一定程度上更滞后于 useTransitionuseDeferredValue = useEffect + transition

3.3 useTransition 解决了什么问题? 可以用节流代替吗?

useTransition 用于在 createRoot 开启的并发特性模式下, 开启并发渲染。主要解决浏览器执行大量渲染工作问题时的卡顿问题。useTransition 返回一个数组, 第一个元素为 isPending, 表示当处于过渡状态的标志; 第二个是 startTransition , 一个方法, 里面的更新任务都会被标记成 过渡更新任务,过渡更新任务在渲染并发场景下,会被降级更新优先级,中断更新, 所以它不会让页面卡顿,React 让这些任务,在浏览器空闲时间执行。

节流防抖 也可以解决大量渲染工作同时渲染卡顿的问题, 但是节流防抖导致更新任务的执行时间变长了, 视图改变的时间也会延长。所以 startTransition节流防抖 的本质区别是: 一方面,节流防抖 本质上也是 setTimeout ,只不过控制了执行的频率,那么通过打印的内容就能发现,原理就是让 render 次数减少了。而 transitions 和它相比,并没有减少渲染的次数。另一方面,节流和防抖需要有效掌握 Delay Time 延时时间,如果时间过长,那么给人一种渲染滞后的感觉,如果时间过短,那么就类似于 setTimeout(fn,0) 还会造成前面的问题。而 startTransition 就不需要考虑这么多。

3.4 useTransition 解决了什么问题? 可以用 setTimeout 替代吗?

useTransition 用于在 createRoot 开启的并发特性模式下, 开启并发渲染。主要解决浏览器执行大量渲染工作问题时的卡顿问题。useTransition 返回一个数组, 第一个元素为 isPending, 表示当处于过渡状态的标志; 第二个是 startTransition , 一个方法, 里面的更新任务都会被标记成 过渡更新任务,过渡更新任务在渲染并发场景下,会被降级更新优先级,中断更新, 所以它不会让页面卡顿,React 让这些任务,在浏览器空闲时间执行。

setTimeout 同样可以解决大量渲染工作同时渲染卡顿的问题, startTransition 相比 setTimeout 的优势和异同是: 一方面, startTransition 的处理逻辑和 setTimeout 有一个很重要的区别,setTimeout 是异步延时执行,而 startTransition 的回调函数是同步执行的。在 startTransition 之中任何更新,都会标记上 transitionReact 将在更新的时候,判断这个标记来决定是否完成此次更新。所以 Transition 可以理解成比 setTimeout 更早的更新。但是同时要保证 ui 的正常响应,在性能好的设备上,transition 两次更新的延迟会很小,但是在慢的设备上,延时会很大,但是不会影响 UI 的响应。另一方面,对于渲染并发的场景下,setTimeout 仍然会使页面卡顿。因为超时后,还会执行 setTimeout 的任务,它们与用户交互同样属于宏任务,所以仍然会阻止页面的交互。那么 transition 就不同了,在 conCurrent mode 下,startTransition 是可以中断渲染的 ,所以它不会让页面卡顿,React 让这些任务,在浏览器空闲时间执行