Endless Fetch Loop Despite useCallback

47 Views Asked by At

I have an issue with my React Native App where I have a URL fetch request to return data when a tab is loaded, but for some reason there is an endless loop between between the callback happening and the try statement, but it doesn't reach the rest of the code and return the object. Am I using useCallback incorrectly?

Logs:

 LOG  ~~ fetchData - try ~~
 LOG  ~~ fetchData ~~
 LOG  ~~ fetchData - try ~~
 LOG  ~~ fetchData ~~
 LOG  ~~ fetchData - try ~~

Fetch Code (useFetch):

import axios from 'axios';
import { useState, useEffect, useCallback } from 'react';

export const useFetch = (method: string, url: string, body: any) => {
  const [isLoading, setIsLoading] = useState(false);
  const [apiData, setApiData] = useState(null);
  const [serverError, setServerError] = useState(null);

  const fetchData = useCallback(async () => {
    console.log('~~ fetchData ~~');
    try {
      console.log('~~ fetchData - try ~~');
      const res = await axios({
        method: method,
        url: url,
        data: body,
      });
      console.log('~~ fetchData - res ~~');
      console.log(res);
      const data = await res?.data;
      console.log('~~ setApiData - useState ~~');
      console.log(`Data: ${data}`);
      setApiData(data);
      setIsLoading(false);
    } catch (error: any | unknown) {
      setServerError(error);
      setIsLoading(false);
    }
  }, [url, method, body]);

  useEffect(() => {
    setIsLoading(true);
    fetchData();
  }, [fetchData]);

  return { isLoading, apiData, serverError };
};

Tab where fetch occurs:

export { useFetch } from '../../hooks/useFetch';

export default function TabTwoScreen() {
  const { isLoading, serverError, apiData } = useFetch(
    'GET',
    'https://jsonplaceholder.typicode.com/posts/1',
    {}
  );
  }
1

There are 1 best solutions below

0
louisrtz On BEST ANSWER

It seems like your useEffect triggers everytime fetchData changes. With the code example you've provided it seems to change every render because body is included in its dependency. Since body is an object, will be a new dependency every render causing fetchData to be recreated and useEffect to run again.

To fix this you can try a already posted answer below your post, by using useMemo, or remove the body from the dependency array and try to refactor your code a bit.