2
votes

I have a Formik with multi step form. Each step is a component which user have to fill out. Components renders depending on "activeStep" state. If user haven't filled out the forms he can't go to the next step and "next" button is disabled. If user filled required fields next button become active. I connected "next" button with "isValid" property.

<button disabled={ !isValid }>

Everything works fine if there is some errors or empty inputs next button stays disable. But when next component renders, "isValid" property stays true until I press to any input, and then it become false and next button gets disable. I need make next button disable as soon as new component renders without focusing to any input.

//conditional component rendering
displayForms = (values, isValid,step) => {
    const { activeStep, allSteps, file, isDisabled } = this.state;
    const { resumeSended, resumeFile } = this.props;
    const formsComponents = {
      1: (
        <Step1
          {...values}
          uploadFile={this.uploadFile}
          filename={file ? file.name : null}
          setFile={this.setFile}
          fileLoaded={resumeFile}
        />
      ),
      2: <Step2 education={values.education} item={this.eduValues} />,
      3: <Step3 experience={values.experience} item={this.experienceValues} />,

    };

    switch(step){
      case 1:  return formsComponents[1];
      case 2:  return  formsComponents[2];
      case 3:  return  formsComponents[3];
    }
  };


  <Formik
            ref={this.resume}
            initialValues={this.initialValues}
            render={({ values, isValid,errors}) => {
              return (
                <Form id='myform'>
                  <div className="jobs-resume-panes">
                      {this.displayForms( values, isValid,this.state.activeStep)}

                  </div>
                  {activeStep === allSteps && (
                    <div className="form-block form-block--checkbox">
                      <Field
                        type="checkbox"
                        name="agree"
                        checked={values.agree}
                        id="agree"
                        validate={val => (val ? undefined : 'error')}
                      />
                    </div>
                  )}
                  <div className="jobs-resume-controls">
                    <button
                      type="button"
                      onClick={this.goPrevStep}
                    >
                      Back
                    </button>
                    <div className="jobs-resume-next">
                      {activeStep === allSteps ? (
                        <button
                          onClick={() => this.submitResume(values, isValid)}
                        >
                         Save
                        </button>
                      ) : (
                        <button
                          disabled={ !isValid }
                          onClick={()=>this.goNextStep()}
                        >
                          Next
                        </button>
                      )}
                    </div>
                  </div>
                </Form>
              );
            }}
          />
2
Set enableReinitialize flag as true. I think it will solve your problem. It is by deafult falseRahul Dey
I am also facing the same problem, setting enableReinitialize to true doesn't help.Rajat Sharma

2 Answers

0
votes

Set enableReinitialize flag as true. I think it will solve your problem. It is by default false in formik.

0
votes

Hope someone might find this answer useful in the future.

To initially disable the submit/next button in the multi step form, along with the isValid property you have to include the dirty property of formik. Thanks to this answer.

So the code will look like this: disabled={!(isValid && dirty)}

This will disable the submit/next button every time the step changes and until all fields that can throw errors are validated.