1

I am trying to set a variable inside an onClick event. I am setting the error messages into the variable.

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

         if (edit_user.email == "") {
             setEditUserError({ email: "Please enter an email!" })
        }

        if (edit_user.company == "") {
           setEditUserError({ ...edit_user_error, company: "Please enter company!" })
       }

And I am showing the error in the form like <span className="text-danger">{edit_user_error.company}</span>

The problem is that when all the fields are empty and when I click the button only the last message is shown. When I make one field empty, and then click the submit button it is working correctly. I tried console.log(edit_user_error) but it is showing empty. What am I doing wrong? Please help

2 Answers 2

3

This is because of batched state updates. React will try to reduce the renders by minimizing the state updates. You can use functional state update to fix this:

if (edit_user.email == "") {
  setEditUserError({ email: "Please enter an email!" });
}

if (edit_user.company == "") {
  // this callback gets executed only when previous state updates are done
  setEditUserError((prev) => ({ ...prev, company: "Please enter company!" }));
}

To clear the errors when fields are valid:

const getErrors = () => {
  return {
    ...(!edit_user.email ? { email: "Please enter an email!" } : {}),
    ...(!edit_user.company ? { company: "Please enter company!" } : {}),
  };
};

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

  setEditUserError(getErrors());
};
Sign up to request clarification or add additional context in comments.

2 Comments

This doesn't work properly. When I enter values and submit, the error messages are not going.
@Akhilesh That's because there's no code to clear the errors if the fields are valid. Not exactly related to the original problem. Anyway updated the answer to clear the errors.
0

React state updates are async, which means they won't run right away. So when running multiple setState to the same state, you can't expect the state from the first setState call to be update it before the second setState call happens.

In short, React is ignoring your earlier setState calls because they happen one after another.

The solution is to put the update into a single call:

    const handleEdit = (e) => {
        e.preventDefault();
         
        let errors = {};

         if (edit_user.email == "") {
             errors.email = "Please enter an email!"
        }

        if (edit_user.company == "") {
           errors.company = "Please enter company!"
       }

      // and then we call state with all the values, only once
      setEditUserError(errors);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.