自定义useFetch挂钩中的无限循环

时间:2020-09-09 07:41:08

标签: javascript reactjs react-hooks render

所以我不确定,到底是什么导致该问题或如何正确解决此问题。

我有一个自定义useFetch挂钩来获取数据。唯一的特别之处是您可以提供一个函数来修改获取的结果。 useFetch钩子是我无法联系到的某个人写的。

下面是一个完整的,隔离的codeandbox示例,以重现此内容:

https://codesandbox.io/s/optimistic-lalande-glhg3?file=/src/App.js:192-326

您可以看到选中的行(192-326)已被注释掉。它是组件上方对象的副本。

在组件内部的init对象中进行注释时,useFetch挂钩开始无限获取URL。

这可能与变量或值的更改/重新呈现有关,但我不明白。

1 个答案:

答案 0 :(得分:3)

每个渲染都会使用新引用创建新对象init,但内容相同。然后,此效果跟踪此引用并执行状态更新。因此状态更新导致重新渲染,从而导致新的初始化对象触发效果...

 useEffect(() => {
    setLoading();
    [...successModifiers, (result) => setResource(result)].reduce(
      (previous, current) => previous.then(current).catch(setError),
      fetch(url, init).catch((error) => setError(error))
    );
  }, [url, init, successModifiers]);
//         ^^^^^

要解决此问题,您可以使用useMemo保留对象引用:

const init = useMemo(() => ({ /*...*/ }));

但是这可能会使useFetch的使用有些笨拙,因此,替代方法是基于深度比较将对象保留在useFetch内。像这样:


function useDeepMemo(object) {
  const ref = useRef(object);

  if (!deepEquals(object, ref.current)) {
    ref.current = object;
  }

  return ref.current;
}