Xameer
Xameer

Reputation: 31237

Set state on form submit in a functional component

In my react typescript app - I have a login component and a handleLoginRequest function which sets the userMessage value:

function Login() {
  let [userMessage, setUserMessage] = useState("");

  return (
    <form className="form-inline" onSubmit={(e) => {
      setUserMessage(handleLoginRequest(e))
    }} >
      <label className="mr-sm-2">Email address:</label>
      <input type="email" className="form-control mb-2 mr-sm-2" placeholder="Enter email" id="email" />
      <label className="mr-sm-2">Password:</label>
      <input type="password" className="form-control mb-2 mr-sm-2" placeholder="Enter password" id="password" />
      <button type="submit" className="btn btn-primary mb-2">Submit</button>
      {userMessage}
    </form>

  );
}

Update: handleLoginRequest is a API request

const handleLoginRequest = (event: any): any => {
  event.preventDefault();

  const data = {
    email: event.target.email.value,
    password: event.target.password.value
  };

  axios.post(`${process.env.REACT_APP_HTTP_PROXY}/api/v1/login`, data)
    .then(res => {
      console.log(res.data);
      return res.data;
    })
    .catch(err => {
      console.log(err);
      return err.message;
    });
}

Expected behavior:

When the form is submitted, the function setUserMessage(handleLoginRequest(e)) is called. I expect that it update the value of userMessage to login request received.

Actual result:

No change in the value of userMessage

What is the fix here?

Upvotes: 3

Views: 221

Answers (1)

Shane Creedon
Shane Creedon

Reputation: 1923

Updated answer per the question modification

The issue is stemming from the fact you're trying to setState based on a axios post request. Axios requests are asynchronous, meaning they will happen out of order with the program control flow. Therefore, to solve this issue, it is important you only make a call to setUserMessage when the request is complete.

Example Code:

axios.post(`${process.env.REACT_APP_HTTP_PROXY}/api/v1/login`, data)
  .then(res => {
    setUserMessage(res.data);
  })
  .catch(err => {
    // Do Something with error response
    setUserMessage("Error: Something with the request went wrong.");
  });

I will link a codesandbox to demonstrate:

https://codesandbox.io/s/focused-leakey-0jer4

Upvotes: 4

Related Questions