AnswerBun.com

react - Infiinite loop when sending axios request (useState problem?)

Stack Overflow Asked by Countour-Integral on January 5, 2022

First I declare these two varaibles to get and set the values I get from the axios request

let tmpFolder = [];
const [folder_JSX,setFolder_JSX] = useState([])

then I send the request

const sendRequest = () => {
  return axios.get(`sample_url`).then(response => {return response.data})
}

sendRequest().then(folder=> {
//loop through each item and append a JSX element into the array
for (let i=0;i <folder.length;i++) {
  tmpFolder.push(<Folder tags={folder[i].tags} name={folder[i].name} description={folder[i].description} date={folder[i].date_created[0]} tagOne={folder[i].tags[0]} tagTwo={folder[i].tags[1]} tagThree={folder[i].tags[2]} tagRest={folder[i].tags.length - 3} />)
}
setFolder_JSX(prev => tmpFolder) // <----- This line is causing an infinite loop
}).catch(err => console.log(err))

The compiler throws Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

which is True (when I remove one prop from the Folder JSX element it does not throw this error but keeps making requests infinitely)

  • First I loop through all the items in the response and then

    – I set the folder state to that array.

The folder_JSX (which gets rendered in the dom) does not change, but the requests keep getting sent.

I can’t figure out what is causing the infinite loop

2 Answers

Every time the state updates, your component function is run again. Because you are calling sendRequest each time the function is called, and then updating the state based on it, you get an endless cycle of rerenders.

You shouldn't be performing side effects - such as API calls - inside the main body of your function anyway. (If you've previously used class components in React, you should think of your function component as the equivalent of render, which just computes the JSX output from the component's current props and state, and should perform no side effects.) When using hooks, you have the useEffect hook for things like this. And in particular, its second argument is an array of variables, for which the effect will only run when one of those values has changed since the last render. This is how you can prevent the effect running on each render - which you must prevent here to stop the infinite updates.

As far as I can tell, this request doesn't depend on any internal state, so it should probably only run when the component first renders. In that case, pass the empty array as second argument.

In short, you should rewrite your code like this:

useEffect(() => sendRequest().then(folder => {
  //loop through each item and append a JSX element into the array
  for (let i=0;i <folder.length;i++) {
    tmpFolder.push(<Folder tags={folder[i].tags} name={folder[i].name} description={folder[i].description} date={folder[i].date_created[0]} tagOne={folder[i].tags[0]} tagTwo={folder[i].tags[1]} tagThree={folder[i].tags[2]} tagRest={folder[i].tags.length - 3} />)
  }
  setFolder_JSX(prev => tmpFolder)
}).catch(err => console.log(err)), []);

Answered by Robin Zigmond on January 5, 2022

It appears as though you have the fetch logic out in the open in the functional component body, something like:

const MyComponent = () => {
  let tmpFolder = [];
  const [folder_JSX, setFolder_JSX] = useState([]);

  const sendRequest = () => {
    return axios.get(`sample_url`).then(response => {
      return response.data;
    });
  };

  sendRequest() // <-- invoked each render cycle
    .then(folder => {
      //loop through each item and append a JSX element into the array
      for (let i = 0; i < folder.length; i++) {
        tmpFolder.push(
          <Folder
            tags={folder[i].tags}
            name={folder[i].name}
            description={folder[i].description}
            date={folder[i].date_created[0]}
            tagOne={folder[i].tags[0]}
            tagTwo={folder[i].tags[1]}
            tagThree={folder[i].tags[2]}
            tagRest={folder[i].tags.length - 3}
          />
        );
      }
      setFolder_JSX(prev => tmpFolder); // <-- state update triggers rerender
    })
    .catch(err => console.log(err));

  ...
};

If this is the case then sendRequest is invoked each render cycle and ultimately updates component state which triggers another render, thus the infinite cycle.

Perhaps you wanted to only fetch data when the component mounts, you can use an effect to do any side-effects:

const MyComponent = () => {
  let tmpFolder = [];
  const [folder_JSX, setFolder_JSX] = useState([]);

  useEffect(() => {
    const sendRequest = () => {
      return axios.get(`sample_url`).then(response => {
        return response.data;
      });
    };
  
    sendRequest()
      .then(folder => {
        //loop through each item and append a JSX element into the array
        for (let i = 0; i < folder.length; i++) {
          tmpFolder.push(
            <Folder
              tags={folder[i].tags}
              name={folder[i].name}
              description={folder[i].description}
              date={folder[i].date_created[0]}
              tagOne={folder[i].tags[0]}
              tagTwo={folder[i].tags[1]}
              tagThree={folder[i].tags[2]}
              tagRest={folder[i].tags.length - 3}
            />
          );
        }
        setFolder_JSX(prev => tmpFolder);
      })
      .catch(err => console.log(err));
  }, []); // <-- empty dependency to run once on component mount

  ...
};

Answered by Drew Reese on January 5, 2022

Add your own answers!

Related Questions

Appending a list in a list using a for loop

2  Asked on November 22, 2021 by syed-ahmed

 

Regular expression to find Specific character in a string

4  Asked on November 22, 2021 by user3061338

       

laravel count records based on each single date

1  Asked on November 22, 2021 by gulzar-ali

       

Change one property in CSS

2  Asked on November 22, 2021 by darek

 

Splitting values in a list and making variables of them

1  Asked on November 22, 2021 by premier12

     

JSX fragment has no corresponding closing tag

1  Asked on November 22, 2021 by chinwe-watkins

   

How to slow down window.location.href on AJAX request

3  Asked on November 22, 2021 by agiftel-longwave

     

Why list initialization disallow narrowing?

0  Asked on November 22, 2021 by alan-jian

   

How can i remove object from nested array?

2  Asked on November 22, 2021 by trajce12

 

How to save model architecture in PyTorch?

3  Asked on November 22, 2021

 

Ask a Question

Get help from others!

© 2023 AnswerBun.com. All rights reserved. Sites we Love: PCI Database, MenuIva, UKBizDB, Menu Kuliner, Sharing RPP, SolveDir