使用 useMemo 或 useCallback VS useRef 清空依赖项

Posted

技术标签:

【中文标题】使用 useMemo 或 useCallback VS useRef 清空依赖项【英文标题】:Empty Dependencies with useMemo or useCallback VS useRef 【发布时间】:2020-03-07 15:39:51 【问题描述】:

在这个GitHub issue 中,我基本上是提议改变:

x = useCallback( ... , []);

收件人:

x = useRef( ... ).current;

两者是相同的,但 useRef React 不会比较依赖关系。

对此有问题的回复:

有没有一种情况,无依赖的 useMemo 或 useCallback 会比 useRef 更好?

我想不出一个,但我可能忽略了一些用例。

那么有人能想到这种情况吗?

【问题讨论】:

【参考方案1】:

因为 useRef(() => ...).current 的输出 是可变的。

这可能会导致代码中出现奇怪的副作用。 我可以随时更改电流值。 https://codesandbox.io/s/confident-monad-vjeuw

这将是不想使用 useRef 的用例

【讨论】:

但是 x = useRef(value).current 永远不会返回可变实例 - ref 永远不会返回; current 是。这与useCallback 版本相同。【参考方案2】:

每个 React Hooks API 文档:

请记住,useRef 不会在其内容更改时通知您。 改变 .current 属性不会导致重新渲染 ...使用 回调 ref 确保即使子组件显示 稍后测量节点(例如响应点击),我们仍然得到 在父组件中通知它并且可以更新 测量。

您可以在here 和here 阅读更多相关信息。

【讨论】:

我想这回答了这个问题,但我怀疑这是不正确的。在沙盒 React 示例中,将 useCallback(x,[]) 更改为 useRef(x) 的效果相同。 useRef(x).current 就是这样。 我希望我错了,但我已经说明了文档错误的原因:github.com/reactjs/reactjs.org/issues/2570 我自己对useCallback(cb, [])useRef(cb).current 并不完全确定。尽管useMemo(cb, [])useRef(cb).current 不同,在某种意义上useMemo“只会在其中一个依赖项发生变化时重新计算记忆值”。与 useRef 相比,无论如何都会重新计算值。 useRef 从不重新计算 - 它总是返回初始值。【参考方案3】:

虽然您可以使用 useRef 来模拟 useCallback 或使用空依赖项,但您不能将它用于所有可能的 useCallback 场景,即在任何依赖项更改时进行记忆。

此外,如果您使用 useCallback with empty dependency 或 useRef 也不会产生太大的性能差异,因为它不必执行任何繁重的比较。

此外,如果您稍微更改函数实现,以便必须在特定参数更改时重新创建它,您可以简单地使用 useCallback 更新实现并添加额外的参数作为依赖项。但是,如果您使用 useRef 实现它,则必须恢复为 useCallback

【讨论】:

谢谢。正如标题所示,这是一个严格的空依赖案例。 @Izhaki 我知道你的问题是严格的空依赖,这就是为什么我提到空依赖没有任何区别。但是当您尝试添加更多更改时,您可能需要进行相当多的重构

以上是关于使用 useMemo 或 useCallback VS useRef 清空依赖项的主要内容,如果未能解决你的问题,请参考以下文章

这是对 useCallback 和 useMemo 的错误使用吗?

useMemo和useCallback:何时使用它们,何时不使用它们

useMemo和useCallback:何时使用它们,何时不使用它们

useMemo和useCallback:何时使用它们,何时不使用它们

useMemo和useCallback:何时使用它们,何时不使用它们

useMemo和useCallback的区别和使用