skip to Main Content

In my react with typescript project I have a ParentComponent that has a ChildComponent where is a Formik with Yup form that has to be validated as the user types. On the ParentComponent I also have a next button that has to be disabled if there are validation errors as the user types on the form.

This is a code snip of ParentComponent:

const [isFormValid, setIsFormValid] = useState<boolean>(true);
const [isNextButtonDisabled, setIsNextButtonDisabled] = useState<boolean>(false);

useEffect(() => {
  if(!isFormValid) {
    setIsNextButtonDisabled(true);
  }
}, [isFormValid]);

const handleNext = () => {
    if (!isFormValid) {
      return;
    }
    
    goNext();
}

return (
<>
    <ChildComponent
        setIsFormValid={setIsFormValid}
        isFormValid={isFormValid}
    />
    
    <CustomButtonComponent
        type="submit"
        form="myFormikForm"
        isDisabled={isNextButtonDisabled}
    />
</>);

And this is the ChildComponent:

type FormProps = {
  isFormValid: boolean;
  setIsFormValid: React.Dispatch<React.SetStateAction<boolean>>;
};

export const ChildComponent: React.FC<FormProps> = ({
  isFormValid
  setIsFormValid,
}) => {
    return(
        <Formik
            initialValues={{email: ''}}
            onSubmit={() => {}}
            validationSchema={emailValidationSchema}
            validateOnChange={true}
            validateOnBlur={true}
        >
           {({ values, errors, handleChange}) => (
                <Form
                    id={"myFormikForm"}
                    controlId={"myFormikForm"}
                    value={values.email}
                    placeholder=""
                    isInvalid={!!errors.email}
                    error={errors.email}
                    onChange={() => {
                        if(errors.email) {
                            setIsFormValid(!isFormValid);
                        }
                    }}
                />
           )} 
 };

This is how I tried to implement it. The validation of the values inside the form works as expected, the validation messages from emailValidationSchema are correctly displayed under the field as the user types, but it seems like the valid state of the field ‘isFormValid’ doesn’t react the ParentComponent and I can’t disable or enable the button based on the validation state of the Formik form as the user types. How could I achive this?

2

Answers


  1. I guess you have to change tha value inside of setIsFormValid.
    It will keep change the boolean value. Try to set False not using negation.

    <Form
                        id={"myFormikForm"}
                        controlId={"myFormikForm"}
                        value={values.email}
                        placeholder=""
                        isInvalid={!!errors.email}
                        error={errors.email}
                        onChange={() => {
                            if(errors.email) {
                                setIsFormValid(!isFormValid); // to False
                            }
                        }}
                    />
    
    Login or Signup to reply.
  2. I think the correct logic is to set the state of the parent component each time there is a change on the input depending on existance of errors.email

    onChange={() => {
      if(errors.email) {
         setIsFormValid(true);
      }else{
        setIsFormValid(false);
      }
    }}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search