乐趣区

关于javascript:useMemo代替useRef

背景

react-compound-timer 库的 useTimer Hook 实现 有这么段代码:

const timer = useMemo(() =>
      new TimerModel({
        initialTime,
        direction,
        timeToUpdate,
        lastUnit,
        checkpoints,
        onChange: (timerValue: TimerValue) =>
          setTimerValues(state => ({ ...state, ...timerValue})),
      }),
    [],);

useMemo的依赖是空数组,所以变量 timer 在组件生命周期里都不会变动,有点相似实例变量。然而 Hooks 里实现实例变量不是 useRef 的专长吗?这里为啥应用的是useMemo?

useMemo代替useRef?

如果只是实现实例变量,那么 useMemo是否能够代替useRef?如:

const ref = useRef(null);
const ref2 = useMemo(() => { current: null}, []);

应用上没问题,但不是最佳实际。

  1. useMemo会跟踪依赖项,并且通过比拟依赖项是否发生变化决定是否从新执行函数。即便依赖项是个空数组,然而外部还是会做局部额定的逻辑。所以性能上比 useRef 要差。
  2. React 对 useMemo 定位只是用于性能优化,并不保障在依赖项不变时,就肯定不会从新执行函数。
  • How to memoize calculations? 里提到:

You may rely on useMemo as a performance optimization, not as a semantic guarantee.

  • Dan 在 twiter:A few small updates to Hooks FAQ based on common questions. 里也强调:

useMemo() is a hint — not a guarantee. React may still choose to“forget”some memoized values to reclaim memory. Don’t rely on it for correctness

所以对于那些确定不须要从新计算的值,则优先应用useRef,不要应用useMemo

参考

整顿自 gitHub 笔记:useMemo 代替 useRef ?!

退出移动版