xdm,又要到饭了,又更新代码了!
总结一下上一篇完成的内容,
- 完成了useContext的实现, 从底层理解运行机制。
有兴趣的可以点这里查看useContext的实现, 从底层理解运行机制
这一篇我们实现useDeferredValue hook。 这个hook的出现就是解决特定情况下需要延迟更新的场景。
比如,有复杂的计算放在了useEffect 里面,useEffect 的依赖值就是val, val就是复杂计算的一部分。那么如果val使用用户点击进行更新,那么useEffect 的复杂计算将会大量重复计算,这直接会是ui渲染卡顿。即一个frame里面如何完成该完成的工作(大量的计算), 代码如下,
function Test({val}) {
const factorial = useMemo(()=>{
// 大量计算的函数
return computeFactorial(val)
},[val])
}
由于val一直变化,即使上面的代码使用了useMemo也无法解决卡顿问题。那么既然卡顿由于大量计算导致,那么是可以配合ric的空闲时间进行延迟计算呢?这个就是useDeferredValue 解决的场景之一。
实现 useDeferredValue
function useDeferredValue(val) {
const [deferredValue , setDeferredValue] = useState(val)
const updateDeferredValue = ()=>{
setDeferredValue(val)
}
useEffect(()=>{
let handle
if (requestIdleCallback !== 'undefined') {
handle= requestIdleCallback(updateDeferredValue)
} else {
handle= setTimeout(updateDeferredValue, 0);
}
return ()=>{
if (typeof requestIdleCallback !== 'undefined') {
cancelIdleCallback(handle)
} else {
clearTimeout(handle)
}
}
}, [val])
return deferredValue
}
实现代码巧妙的尝试使用 ric 进行延迟更新,这样可以避免大量计算进而导致ui更新卡顿。
react 咋么做的
react由于有concurrent mode, 所以它可以赋予任务的优先级权重决定当前的任务运行顺序,这样的原理其实和 requestIdleCallback类似,但是不完全相同。
react 的实现
function useDeferredValue(value) {
const [deferredValue, setDeferredValue] = useState(value)
useEffect(()=>{
// 低优先级任务会排在高优先级任务之后运行,
const handle = scheduleCallback(PRIORITY_LOW, ()=>{
setDeferredValue(value)
})
}, [value])
}
scheduleCallback 以及 useState 的底层实现之前的系列文章已经实现过了,有兴趣的可以查看。
这篇我们尝试实现了一个自己的useDeferredValue版本,然后实现了一个react的版本,也对对于useDeferredValue的使用场景以及解决了什么问题进行了讲解。
那么下一篇将从0-1实现开发 useLayoutEffect 。
如果文章对你有帮助,请点个赞支持一下!
啥也不是,散会。