startTransition:
- startTransition 原理特别简单,有点像 React v17 中 batchUpdate 的批量处理逻辑。
- 就是通过设置开关的方式,而开关就是 transition = 1 ,然后执行更新,里面的更新任务都会获得 transtion 标志。
接下来在 concurrent mode 模式下会单独处理 transtion 类型的更新。
export function startTransition(scope) {
const prevTransition = ReactCurrentBatchConfig.transition;
/* 通过设置状态 */
ReactCurrentBatchConfig.transition = 1;
try {
/* 执行更新 */
scope();
} finally {
/* 恢复状态 */
ReactCurrentBatchConfig.transition = prevTransition;
}
}
useTranstion:
这段代码不是源码,把源码里面的内容进行组合,压缩。
- 从上面可以看到,useTranstion 本质上就是 useState + startTransition 。
- 通过 useState 来改变 pending 状态。在 mountTransition 执行过程中,会触发两次 setPending ,一次在 transition = 1 之前,一次在之后。一次会正常更新 setPending(true) ,一次会作为 transition 过渡任务更新 setPending(false); ,所以能够精准捕获到过渡时间。
function mountTransition(){
const [isPending, setPending] = mountState(false);
const start = (callback)=>{
setPending(true);
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setPending(false);
callback();
} finally {
ReactCurrentBatchConfig.transition = prevTransition;
}
}
return [isPending, start];
}
useDeferredValue:
- 从上面可以看到 useDeferredValue 本质上是 useDeferredValue = useState + useEffect + transition
- 通过传入 useDeferredValue 的 value 值,useDeferredValue 通过 useState 保存状态。
然后在 useEffect 中通过 transition 模式来更新 value 。 这样保证了 DeferredValue 滞后于 state 的更新,并且满足 transition 过渡更新原则。
function updateDeferredValue(value){
const [prevValue, setValue] = updateState(value);
updateEffect(() => {
const prevTransition = ReactCurrentBatchConfig.transition;
ReactCurrentBatchConfig.transition = 1;
try {
setValue(value);
} finally {
ReactCurrentBatchConfig.transition = prevTransition;
}
}, [value]);
return prevValue;
}