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