Reputation: 45
so I'm not sure, whats exactly causing this or how to fix this properly.
I have a custom useFetch hook to fetching data. The only special thing about it is that you can provide a function to modify the result of the fetch. The useFetch hook was written by some guy I can't reach anymore.
Here's a full, isolated codesandbox example to reproduce this:
https://codesandbox.io/s/optimistic-lalande-glhg3?file=/src/App.js:192-326
You can see the selected lines (192-326) are commented out. It's a copy of the object above the component.
When commenting in the init-object that is inside the component, the useFetch hook starts infinitely fetching the url.
This will probably have something to do with variables or values changing / rerendering but I don't get it.
Upvotes: 2
Views: 535
Reputation: 2080
Each render creates new object init
with new reference, but content is the same. Then this effect track this ref AND perform state updates. So then state update leads to re-render, which leads to new init object which trigger effect ...
useEffect(() => {
setLoading();
[...successModifiers, (result) => setResource(result)].reduce(
(previous, current) => previous.then(current).catch(setError),
fetch(url, init).catch((error) => setError(error))
);
}, [url, init, successModifiers]);
// ^^^^^
To solve it you can either persist object ref with useMemo
:
const init = useMemo(() => ({ /*...*/ }));
But this can make usage of useFetch
a bit clumsy, so alternative is to persist object inside useFetch
based on deep comparison. Something like this:
function useDeepMemo(object) {
const ref = useRef(object);
if (!deepEquals(object, ref.current)) {
ref.current = object;
}
return ref.current;
}
Upvotes: 3