Soumalya Bhattacharya
Soumalya Bhattacharya

Reputation: 662

how to call UseState hook's state updater function inside a callback in react.js

I'm having this code where after I get the http request fulfilled, I'm calling the state updater function i.e., setUserName with the response I get from the async function. But I see that UsernameGenerator() just gets called repeatedly like in an infinite loop. I think somehow repeated rendering is taking place here because I have used the UserName as a value for an input in my code.

The thing I want is to set the res as the initial value for the state variable and after setting the value once UsernameGenerator() should never be called again.

Here is the snippet of my code

import { useState } from "react";
import axios from "axios";
const SignUp = () => {
const [UserName, setUserName] = useState("");
const usernameGenerator = async () => {
    let username = await axios.get("https://localhost:5000/GenerateUserName");
    return username.data.username;
  };
  usernameGenerator().then((res) => {
    setUserName(res);
    return res;
  }).catch ((err)=>{
    if(err) throw err;
  });
  return (
  <Input
     color="secondary"
     id="UserName"
     type="text"
     aria-describedby="User-Name"
     value={UserName}
     onChange={(e) => setUserName(e.target.value)}
     className={classes.input}
 />
  );
 }
 export default SignUp;

How do I avoid this infinite loop like condition and have the res as my initial value of the state variable.

Upvotes: 2

Views: 462

Answers (1)

Abhay Sehgal
Abhay Sehgal

Reputation: 1723

You need to put a call in useEffect hooks, like -

import { useEffect } from "react";


useEffect(() => {
    usernameGenerator().then((res) => {
       setUserName(res);

    }).catch ((err)=>{
        // handle error here, instead of throwing
    });
}, []); // here you need to pass empty array as second parameter of useEffect to call it once

Explanation: What you want is to call API on the component mount so by using useEffect with dependency array as empty you can achieve this.

Currently, you're calling it on every render and in the then callback you're updating state which is causing an infinite loop

Upvotes: 3

Related Questions