背景
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}, []);
应用上没问题,但不是最佳实际。
useMemo
会跟踪依赖项,并且通过比拟依赖项是否发生变化决定是否从新执行函数。即便依赖项是个空数组,然而外部还是会做局部额定的逻辑。所以性能上比useRef
要差。- 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 ?!