所以我不确定,到底是什么导致该问题或如何正确解决此问题。
我有一个自定义useFetch挂钩来获取数据。唯一的特别之处是您可以提供一个函数来修改获取的结果。 useFetch钩子是我无法联系到的某个人写的。
下面是一个完整的,隔离的codeandbox示例,以重现此内容:
https://codesandbox.io/s/optimistic-lalande-glhg3?file=/src/App.js:192-326
您可以看到选中的行(192-326)已被注释掉。它是组件上方对象的副本。
在组件内部的init对象中进行注释时,useFetch挂钩开始无限获取URL。
这可能与变量或值的更改/重新呈现有关,但我不明白。
答案 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;
}