elderlyman
elderlyman

Reputation: 590

Why is this async function infinite looping?

I've taken my app to bare minimum to try to understand why it is infinite looping...but I don't get it.

const App = () => {

  console.log("just logging that the app ran!")
  
  const [data, setData] = useState('initial state');
  
  const getAsset = async () => {
  
    console.log("logging that getAsset ran!")

  setData("new state!")
  console.log(data)
}
  
  getAsset();
  
  return (

    <div >
      {data}
    </div>
  );
}

export default App;

Any pointers?

The error message:

react-dom.development.js:14997 Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.

Upvotes: 0

Views: 3631

Answers (5)

uma mahesh
uma mahesh

Reputation: 124

you can use some thing like this 

 fetchSummary(Props).then((d)=>{
    setSummary(d);
    setStatus('success');
    setModel(d.model);
    console.log("response after call" + JSON.stringify(d));
  })

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

//-> triggers one time if we specify empty array

-> fetchSummary is promise function 
-> on promise function you can call then
-> then block will call only once promise is resolved

Upvotes: 0

Usman Fawad
Usman Fawad

Reputation: 26

Your component will re-render on each action performed, re-running the async function again and again. A way to avoid this is using the useEffect hook with a dependency of your choice. This way, the async function will only run when it fulfils a certain condition.

Upvotes: 0

joy08
joy08

Reputation: 9662

Just call the getAsset inside useEffect hook. Not sure why the function is made async though. In your case setData causes a re-render and again calls the getAsset function which results in a loop

Working sandbox : https://codesandbox.io/s/react-hooks-example-forked-0rqb9?file=/src/App.js

const App = () => {

  const [data, setData] = useState("initial state");

  useEffect(() => {
    getAsset();
  }, []);

  const getAsset = async () => {
    setData("new state!");
  };

  return <div>{data}</div>;
};

export default App;

Upvotes: 2

SciDev
SciDev

Reputation: 159

The problem is that App is getting re-run by React every time the state changes, meaning getAsset being called directly in App without any checks to see if it has run already, will cause a loop.

// Runs when the component is rendered.
const App = () => {
  // ...
  getAsset(); // Sets state, re-rendering app.
  // ...
  return (
    <div >
      {data}
    </div>
  );
}

To fix, check to make sure state is only set once or when the new state would be different so no looping behavior can occur.

Upvotes: 1

Omar Khaled
Omar Khaled

Reputation: 509

your code call getAsset() every time component render and getAsset setState (setData) and when you change state the component rerender and it call getAsset again and rerender again ............

you need to call it on mount so use useEffect


const App = () => {

  console.log("just logging that the app ran!")
  
  const [data, setData] = useState('initial state');
  
  const getAsset = async () => {
  
    console.log("logging that getAsset ran!")

  setData("new state!")
  console.log(data)
}
 
 useEffect(() => {
getAsset();

},[])

  
  return (

    <div >
      {data}
    </div>
  );
}

export default App;

Upvotes: 1

Related Questions