使用useMemo或useCallback时的空依赖 vs useRef

16

在这个GitHub问题中,我基本上建议更改:

x = useCallback( ... , []);
收件人:
x = useRef( ... ).current;

这两者相同,但使用useRef时React不会比较依赖项。

有人回复并提出了一个问题:

是否有情况下,没有依赖关系的useMemo或useCallback比useRef更好?

我想不到任何一种情况,但我可能忽略了某些用例。

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

3个回答

8
根据React Hooks API文档:
请注意,useRef不会在其内容更改时通知您。 修改.current属性不会导致重新渲染...使用回调ref确保即使子组件稍后显示测量的节点(例如响应单击),我们仍然会在父组件中收到有关它的通知并且可以更新测量值。
您可以在这里在这里阅读更多相关信息。

我猜这回答了问题,但我怀疑这是不正确的。在沙盒React示例中,将useCallback(x, [])更改为useRef(x)可以达到相同的效果。 - Izhaki
useRef(x).current 就是这样。 - Izhaki
我希望我是错的,但我已经提出了文档错误的理由:https://github.com/reactjs/reactjs.org/issues/2570 - Izhaki
我自己也不是完全确定useCallback(cb, [])useRef(cb).current之间的区别。尽管useMemo(cb, [])useRef(cb).current有所不同,因为useMemo仅在依赖项更改时重新计算记忆值。而useRef无论如何都会重新计算该值。 - Rasuna Khatami
2
useRef 永远不会重新计算 - 它总是返回初始值。 - Izhaki

1

虽然您可以使用 useRef 来模拟 useCallback 或使用空依赖项,但无法将其用于 useCallback 的所有可能场景,后者是在任何依赖项更改时重新记忆。

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

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


1
谢谢。正如标题所示,这是一个严格的空依赖项案例。 - Izhaki
2
@Izhaki 我理解你的问题是关于空依赖项的,这就是为什么我提到在空依赖项的情况下没有任何区别。但是当您尝试添加更多更改时,您可能需要进行相当大量的重构。 - Shubham Khatri

0

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

这可能会在您的代码中引起奇怪的副作用。 我可以随时更改current的值。 https://codesandbox.io/s/confident-monad-vjeuw

这就是不想使用useRef的用例。


2
但是 x = useRef(value).current 永远不会返回可变的实例 - 永远不会返回 ref;只会返回 current。这和 useCallback 版本是一样的。 - Izhaki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接