在钩子依赖性阵列中可观察到无限循环

发布于 2025-01-22 20:22:23 字数 496 浏览 0 评论 0原文

我有一个自定义挂钩,该挂钩接收一组可观察到的参数,然后(在使用效果钩中)在可观察到的可观察到一个值时,都会设置内部状态。

export const myHook = (obs$: Observable<any>) => {
   const [state, setState] = useState();

   useEffect(() => {
      obs$.subscribe((x) => setState(x));
   }, [obs$]);
 
   return state;
}

这会导致无限循环,我猜是因为obs $对象的某些属性随着它的解决而在变化。它可以与一个空的依赖性数组一起使用,但是为了正确的目的,我不想这样做,因为如果obs $确实在自定义挂钩范围之外进行了重新计算(不确定为什么会发生这种情况,但仍然如此)。

I have a custom hook which receives an array of Observables as a parameter, then (in a useEffect hook) sets internal state any time the Observable emits a value.

export const myHook = (obs$: Observable<any>) => {
   const [state, setState] = useState();

   useEffect(() => {
      obs$.subscribe((x) => setState(x));
   }, [obs$]);
 
   return state;
}

This causes an infinite loop, I'm guessing because some property on the obs$ object is changing as it resolves. It works with an empty dependency array, but for the sake of correctness I don't want to do that because it should recalculate if obs$ is genuinely changed outside of the scope of the custom hook (not sure why this would ever happen, but still).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一瞬间的火花 2025-01-29 20:22:23

观察物是对象。以下表达式为fals:{} === {}(类似地,==和其他“类似”对象)(在此处提供更多信息)。

React的使用效果挂钩使用===比较依赖项以查看它们是否已更改。由于每个obs $都有不同的引用,因此您需要找到一种方法来确保将相同的确切对象引用传递给钩子。如果===比较器返回true,则useffect将不会再次运行。

这就提出了一个问题:除非更改,否则我们如何确保obs $具有相同的参考

有很多方法,但是 usememo usecallback 是可以帮助此帮助的工具。每个它们都有自己的依赖性,但不应在您的钩子中使用它们,因为您需要依赖相同的obs $与每个函数调用更改的相同问题。

如果obs $具有退出方法,则在组件重新租赁(或删除)时,我会退订。

export const useHook = (obs$: Observable<any>) => { // hooks should start with the `use` prefix
   const [state, setState] = useState();

   useEffect(() => {
      obs$.subscribe((x) => setState(x));

      return () => obs$.unsubscribe() // return a cleanup function
   });
 
   return state;
}

在React文档中,有一个类似的示例

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    // Clean up the subscription
    subscription.unsubscribe();
  };
});

Observables are objects. The following expression is false: {} === {} (similarly for == and other "similar" objects) (more info here).

React's useEffect hook uses === to compare dependencies to see if they've changed. Since each obs$ has different references, you'll need to find a way to ensure that the same exact object reference is passed to your hook. If the === comparator returns true, then the useEffect won't run again.

That begs the question: How do we ensure that the obs$ has the same reference unless it changes?

There are many ways, but useMemo and useCallback are tools that can help with this. Each of those have their own dependencies, but they shouldn't be used in your hook since you'll have the same problem of needing to depend on the same obs$ that changes with each function call.

If obs$ has an unsubscribe method, then I would unsubscribe when the component re-renders (or unmounts).

export const useHook = (obs$: Observable<any>) => { // hooks should start with the `use` prefix
   const [state, setState] = useState();

   useEffect(() => {
      obs$.subscribe((x) => setState(x));

      return () => obs$.unsubscribe() // return a cleanup function
   });
 
   return state;
}

In the React docs, there is a similar example.

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    // Clean up the subscription
    subscription.unsubscribe();
  };
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文