1

state isn't reflecting change immediately causing me to have to fun onSubmit twice to get the form to submit

If you want to perform an action on state update, you need to use the useEffect hook, much like using componentDidUpdate in class components since the setter returned by useState doesn 't have a callback pattern

from Link to suggested question

But I'm Honestly confused on how to implement an on Submit into a use effect I'm sorry I'm new to react

  const onSubmit = async(data) = > {
      setNameError(nameValidation(data.name));
      setphoneError(phoneNumberValidation(data.phoneNumber));
      setEmailError(emailValidation(data.email));
      setMessageError(messageValidation(data.message));

//Here is where I'm getting caught up, in react dev tools the above states are being set to false but below the noErrors Variable is still reading false after all conditions check true the no Errors is still getting the old values for some reason I even used a settimeout method.

   let noErrors = (!nameError && !phoneError && !emailError && !messageError);
      if (noErrors) {
          try {
              //  const templateParams = {
              //    name: data.name,
              //    email: data.email,
              //    number: data.phoneNumber,
              //    message: data.message,
              //  };
              //  await emailjs.send(
              //    process.env.REACT_APP_SERVICE_ID,
              //    process.env.REACT_APP_TEMPLATE_ID,
              //    templateParams,
              //    process.env.REACT_APP_USER_ID
              //  );
              reset();
              toastifySuccess();
          } catch (e) {
              console.log(e);
          }
      }
  };

const hasCharacter = /[a-zA-Z]/g;
export const nameValidation = function nameValidation(name) {
    if (name.length > 30) {
        return 'This field only accepts 30 characters';
    }
    if (name.length < 5) {
        return 'This field requires five characters';
    }
    if (/\d/.test(name)) {
        return ' This field cannot contain numbers';
    }
    if (!name.includes(' ')) {
        return 'This Field Requires A Space';
    }
    return false;
};
export const phoneNumberValidation = (number) = > {
    if (number.length !== 10) {
        return 'A Phone Number Must be ten digits';
    }
    if (hasCharacter.test(number)) {
        return 'A Phone Number Shouldnt Contain A Letter';
    }
    return false;
};
export const emailValidation = (email) = > {
    if (email.length > 30) {
        return 'This field only accepts 30 characters';
    }
    if (email.length < 5) {
        return 'This field requires five characters';
    }
    if (!email.includes('@')) {
        return 'Email Addresses require @ Symbol';
    }
    return false;
};
export const messageValidation = (message) = > {
    if (message.length > 500) {
        return 'This field only accepts 500 characters';
    }
    if (message.length < 5) {
        return 'This field requires five characters';
    }
    return false;
};
JustAsking
  • 121
  • 7
  • 1
    `setX` methods only effect the next render – mousetail Jul 01 '21 at 07:25
  • there's a great answer in the link you shared https://stackoverflow.com/a/58877875/3064893 – van Jul 01 '21 at 07:25
  • I read both of the top answers and I'm still stuck It says add it to a useffect or add the variable to the dependency I'm not understanding how to do this correctly – JustAsking Jul 01 '21 at 07:34
  • How do i effect the current render? – JustAsking Jul 01 '21 at 07:41
  • 1
    Can you update your question with a more [complete and comprehensive code example](https://stackoverflow.com/help/minimal-reproducible-example)? It's a bit difficult to see where you are updating state and then expecting it to be updated immediately. The link you've mentioned is the link I was about to mark this as a duplicate of but I can't tell where you are getting tripped up. – Drew Reese Jul 01 '21 at 07:50
  • Sure i just updated it – JustAsking Jul 01 '21 at 08:03
  • And so you've applied the suggested fix and moved the code after the state updates into an `useEffect` with appropriate dependencies? – Drew Reese Jul 01 '21 at 08:08
  • I cant move it into a use effect because its inside of the on submit that's where I'm confused – JustAsking Jul 01 '21 at 08:12
  • 1
    Right, it needs to be moved to a `useEffect` with dependency so it can access the updated state you are setting in the submit handler. – Drew Reese Jul 01 '21 at 08:23

1 Answers1

1

Here there are 2 ways to solve your issue.

Store error in local variable and use those variables to setState and check noError.

const onSubmit = async(data) = > {
      const nameErr = nameValidation(data.name);
      const phoneErr = nameValidation(data.phoneNumber);
      const emailErr = nameValidation(data.email);
      const messageErr = nameValidation(data.message);
      setNameError(nameErr);
      setphoneError(phoneErr);
      setEmailError(emailErr);
      setMessageError(messageErr);
      let noErrors = (!nameErr && !phoneErr && !emailErr && !messageErr);
      // rest of your code
}

use useEffect to calculate noErrors

const onSubmit = async(data) = > {
    setNameError(nameValidation(data.name));
    setphoneError(phoneNumberValidation(data.phoneNumber));
    setEmailError(emailValidation(data.email));
    setMessageError(messageValidation(data.message));
}
useEffect(() => {
    const submitForm = async () => {
      let noErrors = (!nameErr && !phoneErr && !emailErr && !messageErr);
      if (noErrors) {
          try {
              //  const templateParams = {
              //    name: data.name,
              //    email: data.email,
              //    number: data.phoneNumber,
              //    message: data.message,
              //  };
              //  await emailjs.send(
              //    process.env.REACT_APP_SERVICE_ID,
              //    process.env.REACT_APP_TEMPLATE_ID,
              //    templateParams,
              //    process.env.REACT_APP_USER_ID
              //  );
              reset();
              toastifySuccess();
          } catch (e) {
              console.log(e);
          }
        }
     }
     submitForm();

},[nameError, phoneError, emailError, messageError])
Amit Chauhan
  • 6,151
  • 2
  • 24
  • 37