简体   繁体   中英

Infinite loop in a custom useFetch hook

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.

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM