note icon indicating copy to clipboard operation
note copied to clipboard

useMemo代替useRef ?!

Open yaofly2012 opened this issue 4 years ago • 1 comments

背景

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定位只是用于性能优化,并不保证在依赖项不变时,就一定不会重新执行函数。

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

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

参考:

  1. How to memoize calculations?
  2. Question: Can useMemo be used instead of useRef?
  3. useCallback vs useRef misguidance (confounding useRef with object ref)

yaofly2012 avatar Sep 20 '20 10:09 yaofly2012

Useful

ben1one avatar Nov 14 '22 13:11 ben1one