为何useMemo钩子无法在该场景下避免不必要的计算?
useMemo 失效问题分析与解决
先拆解两种场景的核心原因:
场景1:items 声明在组件外部
你误以为第一次点击会耗时,是混淆了执行时机——items 是组件加载前就创建好的全局常量,组件首次挂载时,useMemo 就会执行一次 items.find(),这个过程在组件渲染阶段完成,而非点击按钮时。后续点击修改 count 触发组件重渲染时,items 的引用从未改变,useMemo 直接返回缓存结果,自然不会有耗时操作,点击也就流畅。
场景2:items 声明在组件内部
每次组件重渲染(比如点击按钮改变 count),都会重新创建整个 items 数组,新数组的引用和旧数组完全不同。useMemo 的依赖数组 [items] 检测到引用变化,就会重复执行 find() 操作,连续点击等于重复跑大量计算,必然卡顿。
正确处理方式
情况1:静态数据(不依赖组件内部状态/Props)
维持当前把 items 放在组件外部的写法即可,这是最优解——useMemo 仅在组件首次挂载时执行一次,后续完全复用缓存结果。
情况2:动态数据(依赖组件内部状态/Props)
如果 items 必须在组件内生成(比如要根据 Props 动态调整),要用 useMemo 包裹 items 的创建,保证其引用稳定:
import { useMemo, useState } from "react"; export default function UseMemoExample() { const [count, setCount] = useState(0); // 用 useMemo 包裹 items 创建,依赖为空则仅生成一次 const items = useMemo(() => { return new Array(1_999_999).fill(0).map((_, i) => { return { id: i, isSelected: i === 1_999_998, }; }); }, []); // 若依赖Props/其他状态,需添加到依赖数组中 const selectedItem = useMemo(() => { return items.find((item) => item.isSelected); }, [items]); return ( <div className="container"> <h2>useMemo</h2> <p>Count is {count}</p> <p>Selected Item is {selectedItem?.id}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }
这样 items 的引用只会在依赖变化时更新,selectedItem 的 useMemo 也仅在 items 真的变化时重新计算,避免了不必要的重复执行。
内容的提问来源于stack exchange,提问作者kylehink97
相关产品推荐
相关产品推荐

