背景

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 ?!