Lara
Lara

Reputation: 3021

Early exit from useEffect hook causing 'Error: too many re-renders'

I have a react custom hook from which i need an early exit, below is my code for the same

export const useGetData = (url) => {
  const [state, setState] = useState([]);

  let isNew = true;
  let dtFromC = [];
  dtFromC = useRetrieve(key);
  if (dtFromC.length > 0) {
    setState({
      dtFromC
    });
    isNew = false;
  }

  useEffect(() => {
      if (isNew) {
        fetch(url, {
          method: 'Post',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(body)
        }).then(response => response.json())
        setState({
          response
        });
      ).catch(error =>
        console.error('Error:', error)
      );
    }
  }, [url]);

  return state;
}

In the above code, useRetrieve(key) is another custom hook which is called and it returns an array, on checking if array is not empty, i want to update the state and make isNew = false so that, down code should not execute but its giving me aforementioned error. what's wrong in my code and how can i correct it?

Upvotes: 0

Views: 603

Answers (1)

Ori Drori
Ori Drori

Reputation: 191936

You've created an infinite loop:

dtFromC = useRetrieve(key); // you get dtFromC
if (dtFromC.length > 0) { // it's length is greater than 0
  setState({ dtFromC }); // you set the state which causes a rerender, and you start the loop again
  isNew = false;
}

You should move the handling to dtFromC to the useEffect, which checks if anything changed. If dtFromC changed, it checks if we need to update the state (length > 0) or make a fetch call.

Example (not tested):

export const useGetData = (url) => {
  const [state, setState] = useState([]);
  const dtFromC = useRetrieve(key);

  useEffect(() => {
    if (dtFromC.length > 0) {
      setState({ dtFromC });
    } else {
      fetch(url, {
          method: 'Post',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(body)
        })
        .then(response => response.json())
        .then(response => setState({ response }))
        .catch(error => console.error('Error:', error));
    }
  }, [url, dtFromC, setState]);

  return state;
}

Upvotes: 2

Related Questions