Published on

Using YUP with Material-UI TextField

Authors
  • Name
    Ripal & Zalak
    Twitter

Using YUP with Material-UI TextField

Integrating Material-UI, Formik, and YUP can help create a robust form validation system. This guide will show how to properly validate Material-UI TextField inputs using YUP within Formik.

Why Use YUP with Material-UI?

  • YUP provides a schema-based validation system.
  • Formik simplifies form handling in React.
  • Material-UI offers a great UI experience with TextField.

Setting Up Formik with Material-UI TextField

Formik’s built-in <Field /> component does not automatically integrate with Material-UI’s TextField. You must either use a custom component or an existing library.

1. Custom Input Component for Formik & Material-UI

Instead of directly using <TextField />, create a custom component:

import * as React from 'react'
import { TextField } from '@mui/material'
import { Field, ErrorMessage } from 'formik'
import * as Yup from 'yup'
import { Formik, Form } from 'formik'

const CustomTextInput = ({ field, form: { touched, errors }, ...props }) => (
  <TextField
    {...field}
    {...props}
    error={touched[field.name] && Boolean(errors[field.name])}
    helperText={touched[field.name] && errors[field.name]}
  />
)

const validationSchema = Yup.object({
  username: Yup.string().required('Required').min(8, 'Too Short!').max(20, 'Too Long!'),
  password: Yup.string()
    .required('Required')
    .min(10, 'Too Short!')
    .matches(/^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[^a-zA-Z\d\s:]).*$/, {
      message: 'Password must contain uppercase, lowercase, number, and special character.',
    }),
})

const MyForm = () => {
  return (
    <Formik
      initialValues={{ username: '', password: '' }}
      validationSchema={validationSchema}
      onSubmit={(values) => alert(JSON.stringify(values, null, 2))}
    >
      {({ isSubmitting }) => (
        <Form>
          <Field
            name="username"
            component={CustomTextInput}
            label="Username"
            variant="outlined"
            fullWidth
          />
          <ErrorMessage name="username" component="div" className="error" />

          <Field
            name="password"
            component={CustomTextInput}
            label="Password"
            type="password"
            variant="outlined"
            fullWidth
          />
          <ErrorMessage name="password" component="div" className="error" />

          <button type="submit" disabled={isSubmitting}>
            Submit
          </button>
        </Form>
      )}
    </Formik>
  )
}

export default MyForm

2. Using formik-material-ui Library

Instead of creating a custom component, use formik-material-ui:

npm install formik-material-ui

Then modify your form:

import { Field, Form, Formik } from 'formik'
import { TextField } from 'formik-material-ui'
;<Formik
  initialValues={{ username: '' }}
  validationSchema={Yup.object({ username: Yup.string().required('Required') })}
>
  <Form>
    <Field component={TextField} name="username" label="Username" />
  </Form>
</Formik>

FAQ

1. Why is my validation not working?

Formik's Field component must be used for validation to trigger correctly. Make sure you're passing the custom component prop.

2. How do I style errors differently?

You can override Material-UI styles with sx prop or use CSS classes.

3. Can I validate dynamically based on other fields?

Yes, use YUP’s .when() method to conditionally validate fields based on another field’s value.