How to manage the prop "disabled" of a multi step form buttons with Formik?

Asked

Viewed 21 times

1

The Formik provides a call prop isValid, which already solves the problem of defining when the form button should be disabled. The problem is that this apparent does not work in a multi step form, as the isValid of step current form suffers interference from the properties of other Steps. With that said, I would like to know how I can manipulate the activation of buttons without having to use states in the React.

Index.jsx:

import React, { useState } from 'react';
import { Formik } from 'formik';

import nameSchema from '../../schema/nameSchema'
import emailSchema from '../../schema/emailSchema'

import Email from './Email';
import Name from './Name';

const WizardForm = () => {
  const [step, setStep] = useState(1)

  const nextStep = () => {
    setStep(step + 1)
  }

  const prevStep = () => {
    setStep(step - 1)
  }

  const currentStepSchema = () => {
   if(step === 1) {
     return nameSchema
   }

   if(step === 2) {
     return emailSchema
   }
  }

  return (
    <Formik
      initialValues={{ name: '', email: '' }}
      validationSchema={currentStepSchema()}
    >
      {
        ({ isValid }) => (
          <>
            <Name
              isValid={isValid}
              nextStep={nextStep}
              step={step}
            />

            <Email
              isValid={isValid}
              prevStep={prevStep}
              nextStep={nextStep}
              step={step}
            />
          </>
        )
      }
    </Formik>
  );
}

export default WizardForm;

Name.jsx:

import React from 'react';
import { ErrorMessage, Field, Form } from 'formik';

const Name = ({ step, nextStep, isValid }) => {
  if (step !== 1) {
    return null
  }

  return (
    <Form>
      <Field
        name='name'
        type='text'
        placeholder='type your name'
      />

      <div>
        <ErrorMessage name='name' />
      </div>

      <button disabled={!isValid} onClick={nextStep}>Next</button>
    </Form>
  );
}

export default Name;

Email.jsx

import React from 'react';
import { ErrorMessage, Field, Form } from 'formik';

const Email = ({ step, nextStep, prevStep, isValid }) => {
  if (step !== 2) {
    return null
  }

  return (
    <Form>
      <Field
        name='email'
        type='text'
        placeholder='type your Email'
      />

      <div>
        <ErrorMessage name="email" />
      </div>

      <button onClick={prevStep}>Prev</button>
      <button disabled={!isValid} onClick={nextStep}>Next</button>
    </Form>
  );
}

export default Email;

nameSchema.js:

import * as Yup from 'yup'

export default Yup.object().shape({
  name: Yup.string().min(2).required()
})

emailSchema.js:

import * as Yup from 'yup'

export default Yup.object().shape({
  name: Yup.string().email().required()
})

As you can see in this example, the click validation works perfectly on the Name step, but it doesn’t work on Email, because there is an interference of the properties coming from Name

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.