petrushka_95
petrushka_95

Reputation: 79

How to wait until state is updated

I am working with React and I am having trouble with the state, because it doesn't update inmediately. I know this question has been asked before, but I am having trouble also with dealing with async and await. It doesn't seem to work with that either (maybe I'm not putting it in the right place).

I have a form, and it logs in before updating the errors in the state

Here is the code

   import React, { useState } from "react";

function App() {
  const [errorName, setErrorName] = useState(false);
  const [errorPassword, setErrorPassword] = useState(false);

  const handleSubmit = (e) => {
    e.preventDefault();

    if (!e.target[0].value) {
      setErrorName(true);
    }
    if (!e.target[1].value) {
      setErrorPassword(true);
    }
    if (!errorName && !errorPassword) {
      alert("You have logged in succesfully!");
    }
  };
  return (
    <div className="App">
      <header className="App-header">
        <form onSubmit={handleSubmit}>
          <input placeholder="enter your name" />
          <p style={errorName ? { display: "block" } : { display: "none" }}>
            You have not entered your name
          </p>
          <input placeholder="enter your password" />
          <p style={errorPassword ? { display: "block" } : { display: "none" }}>
            You have not entered your password
          </p>
          <button type="submit"> Submit</button>
        </form>
      </header>
    </div>
  );
}

export default App;

Upvotes: 0

Views: 792

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 371188

Save the values in local variables:

const handleSubmit = (e) => {
  e.preventDefault();
  const newErrorName = !e.target[0].value;
  const newErrorPassword = !e.target[1].value;
  if (newErrorName) {
    setErrorName(true);
  }
  if (newErrorPassword) {
    setErrorPassword(true);
  }
  if (!newErrorName && !newErrorPassword) {
    alert("You have logged in succesfully!");
  }
};

But you should also consider using the required attribute instead, to let the user's browser handle it:

<input required placeholder="enter your name" />
<input required placeholder="enter your password" />

If you have to wait for the state to update, you can use useEffect. Remove the alert from the above, and add in:

setFormJustChanged(true);

to handleSubmit, and add:

const [formJustChanged, setFormJustChanged] = useState(false);
useEffect(() => {
  if (formJustChanged && (errorName || errorPassword)) {
    // There was an error
  } else {
    alert("You have logged in succesfully!");
  }
  // Don't enter this again until the form validates again
  setFormJustChanged(false);
}, [errorName, errorPassword, formJustChanged]);

Upvotes: 2

Related Questions