xdm,又要到饭了,又更新代码了!
总结一下上一篇完成的内容,
- 配合fiber改进了useEffect的实现, 从底层理解运行机制。
有兴趣的可以点这里查看重构useEffect的实现
这一篇我们实现一个常用的api,useMemo
简单介绍
useMemo 是 React 中用于性能优化的 Hook。它允许你记忆(缓存)一个计算结果,只有当其依赖项发生变化时才重新计算。这样可以避免在每次渲染时都进行昂贵的计算,提升应用性能。
基本用法:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
computeExpensiveValue:一个耗时的计算函数。- 依赖项数组
[a, b]:只有当a或b发生变化时,computeExpensiveValue才会重新执行,memoizedValue才会更更新。
关键点:
- 缓存机制:
useMemo会记忆上一次的计算结果,并在依赖项未变化时返回缓存值。 - 依赖项管理:正确管理依赖项数组,确保缓存的准确性。
实现原理
实现 useMemo 需要以下几个步骤:
- 存储缓存值和依赖项:在
hooks数组中,为每个useMemoHook 存储其缓存值和依赖项。 - 依赖项比较:每次渲染时,比较当前依赖项与上一次的依赖项,判断是否需要重新计算。
- 返回缓存值:如果依赖项未变化,返回上一次的缓存值;否则,重新计算并更新缓存值。
接下来我们来实现一下(实现的代码会用到之前几篇完成的代码)。useMemo 关键的点就是缓存在哪里,从哪里提取缓存。其实如果你阅读了之前的几篇fiber架构的实现,对你来说就是非常自然就能理解的。其原理就是借助double buffing,即双fiber树。每次运行会优先对比依赖项,如果没有变化+不是首次渲染,则尝试直接从current fiber 树找出对应的fiber获取缓存而不是重新运算。
function useMemo(factory, deps) {
const oldHook = workInProgress.alternate && workInProgress.alternate.hooks && workInProgress.alternate.hooks[workInProgress.currentHook]
const hasChanged = oldHook ? !deps || deps.some((dep, index)=> dep !== oldHook.deps[index]) : true
const hook = {
value: hasChanged ? factory() : oldHook.value,
deps: deps
}
workInProgress.hooks.push(hook)
workInProgress.currentHook++
return hook.value
}
详细解析:
-
获取旧 Hook:
- 从交替 Fiber (
alternate) 中获取旧的useMemoHook, 从 current fiber 树。
- 从交替 Fiber (
-
判断依赖项是否变化:
- 如果依赖项数组
deps中有任何一个项发生变化,hasChanged为true,表示需要重新计算。 - 如果没有提供
deps,默认认为依赖项已变化。
- 如果依赖项数组
-
创建新 Hook:
- 如果
hasChanged为true,执行factory函数并存储返回值。 - 否则,使用上一次的缓存值。
- 如果
-
添加到 Hooks 列表:
- 将新 Hook 对象添加到当前 Fiber 的
hooks数组。 - 递增
currentHook索引,以确保 Hook 的调用顺序一致(这个已经前几篇反复提过了)。
- 将新 Hook 对象添加到当前 Fiber 的
-
返回缓存值:
- 返回
hook.value,即当前的缓存值。
- 返回
useCallback 的实现
function useCallback(callback, deps) {
return useMemo(() => callback, deps);
}
解释:
useCallback实际上是useMemo的一种特殊用法,返回一个记忆的回调函数。- 通过将
callback包装在一个函数中传递给useMemo,确保只有当依赖项变化时,callback才会被重新创建。
下一篇将从0-1开发useSyncExternalStore 。
如果这样的长度/强度你觉得可以接受,觉得有帮助,可以继续阅读下一篇,实现一个 Mini React:核心功能详解 - useSyncExternalStore的实现 。
如果文章对你有帮助,请点个赞支持一下!
啥也不是,散会。