React 16.8版本引入了许多内置的Hook,其中之一就是 useMemo
。useMemo
是一种记忆化(memoization)技术,它可以增加性能,帮助我们避免在每次渲染时都进行复杂的计算。
在本篇教程中,我将用易于理解的方式,通过实例和对比,进行深入分析 useMemo
的概念与应用。
useMemo
useMemo
是一个React hook,用于返回一个记忆化的值。这个hook只在其相关依赖发生变化时才重新执行创建函数进行计算。如果依赖的值没有变化,useMemo
将返回以前存储的记忆值。
javascriptconst memoizedValue = useMemo(()=>{ // 在这里执行复杂缓慢的计算 return complexComputation(input); }, [input]); // 依赖于input的更改
下面让我们通过一个具体的例子来深入理解 useMemo
。
设想我们正在构建一个电子音乐播放器。对于每首歌曲,我们需要将其长度(秒数)转化为 "分:秒" 的格式。例如,90秒要显示为 “1:30”。
以下是未使用 useMemo
的版本:
javascriptfunction MusicPlayer({ songDuration }) { const durationInMinSec = `${Math.floor(songDuration / 60)}:${songDuration % 60 < 10 ? '0' : ''}${songDuration % 60}`; return ( <div> <p>Song Duration: {durationInMinSec}</p> </div> ); }
此时,每当 songDuration
发生改变,转换操作都会重新进行,导致不必要的消耗。为了优化,我们可以使用 useMemo
来避免重复计算:
javascriptfunction MusicPlayer({ songDuration }) { const durationInMinSec = useMemo(() => { return `${Math.floor(songDuration / 60)}:${songDuration % 60 < 10 ? '0' : ''}${songDuration % 60}`; }, [songDuration]); return ( <div> <p>Song Duration: {durationInMinSec}</p> </div> ); }
现在 useMemo
会记住上一次的**songDuration
**计算结果,只有当 songDuration
值真正发生变化时才会重新执行函数并返回新的结果。
useMemo
与 useCallback
的区别相对于 useCallback
,useMemo
更专注于优化复杂的计算或者保持对象和数组的引用不变。
useCallback(fn, deps)
等同于 useMemo(() => fn, deps)
。也就是说 useCallback
是记忆化函数(reference equality),而 useMemo
是记忆化计算值。
useMomo
的实现原理在React Hooks内部,useMemo
会为每一个Hook维护一个链表,存储每次计算的结果,然后根据输入的依赖数组,去进行Hash匹配,如果当前计算的依赖数组在链表中找到对应的匹配项,那么就返回相关的值,这样就避免了不必要的计算和渲染,提高了效率。
希望这本教程能帮助你了解React的 useMemo
,如何正确地使用它,以及在你的应用中为何使用它。记住,使用 useMemo
是有成本的(记忆化存储值需要空间),所以请根据实际需要,明智地利用它,避免对整个应用性能的影响。