DEV Community

Cover image for 2 ways to build forms using formik with Material UI + Yup!
Osmar Faria
Osmar Faria

Posted on

2 ways to build forms using formik with Material UI + Yup!

So, you've diving into the world of React, and, like me, you've found yourself using Formik to simplify form management while also making use of Material UI for attractive user interfaces. In this post, we'll explore two methods to combine these tools, resulting in functional and visually appealing forms.

First things first, make sure you have the libraries required installed:

npm install @mui/material @emotion/react @emotion/styled
Enter fullscreen mode Exit fullscreen mode
 npm install formik
Enter fullscreen mode Exit fullscreen mode
 npm install yup
Enter fullscreen mode Exit fullscreen mode

Let's start with a basic example, laying the foundation for Formik's operation, including initial values, a validation schema, and an onSubmit function. We'll utilize Yup to create a straightforward validation schema.

import * as yup from 'yup'

  const initialValues = {
    name: '',
    surname: '',
    phone: '',
    age: '',
  }

  const validationSchema = yup.object({
    name: yup.string().required().max(25).min(2),
    surname: yup.string().required().max(25).min(2),
    phone: yup.string().required(),
    age: yup.number()
  })

  const onSubmit = (data) => {
    console.log(data)
  }

Enter fullscreen mode Exit fullscreen mode

Now, let's dive into the first way to integrate Formik with Material UI. We'll access the Formik component within a function to combine it with Material UI:

import { Form, Formik } from "formik";

import { Button, Card, TextField } from "@mui/material";

...

<Card>
  <Formik
    initialValues={initialValues}
    validationSchema={validationSchema}
    onSubmit={onSubmit}
  >
    {(formik) => (
      <Form>
        <TextField
          label="Name"
          name="name"
          {...formik.getFieldProps("name")}
        />
    ...
        <Button
         variant="contained"
         type="submit"
         color="success"
        >
         Submit
        </Button>
      </Form>    
    )}
  </Formik>
</Card>
...


Enter fullscreen mode Exit fullscreen mode

Using {...formik.getFieldProps("name")} simplifies form state management, automatically handling values, onBlur, and onChange events, along with error handling, for the 'name' field.

Next, let's ensure our validation messages appear in Material UI, but only after the user has interacted with the field.

Input field for user name

To achieve this, we can use Formik in conjunction with the Material UI TextField's error and helperText properties:


...

<TextField
  label="Name"
  name="name"
  {...formik.getFieldProps("name")}    
  error={formik.touched.name && !!formik.errors.name}
  helperText={formik.touched.name && formik.errors.name}
/>
...

Enter fullscreen mode Exit fullscreen mode

Now, if you require more control over the TextField component, there's another approach to integrate it. You can wrap the TextField with the <Field> component from Formik. This grants you extra resources, such as custom validation functions and access to meta data:

...

// While Formik can handle this validation as well, let's explore a custom approach for the sake of this example :)

const customValidation = (value) => {
  const regex = /^[A-Za-z\s]+$/; // Regular expression to match alphabets and spaces

  if (!value || !regex.test(value)) {
    return 'Name should contain only letters and spaces';
  }
  return undefined; // Validation passed
};

...

<Field name="name" validate={customValidation}>
  {({ field, meta }) => (
    <TextField
      {...field}
      label="Name"
      error={meta.touched && !!meta.error}
      helperText={meta.touched && meta.error}
    />
  )}
</Field>

Enter fullscreen mode Exit fullscreen mode

That's it for this post. I hope it has helped clarify how to move forward if you are trying to implement these tools together! 😄

Top comments (0)