# React Form Validation using Yup

Form validation is a crucial aspect of web development, ensuring that user inputs are correct, complete, and formatted properly before submission. In [React](https://react.dev/learn), form validation involves managing the state, handling input changes, and providing feedback to users. This process can be achieved through controlled components, where form elements derive their values from the component's state, allowing developers to validate and control input data efficiently.

[Yup](https://github.com/jquense/yup) is a popular JavaScript schema validation library that provides an easy and powerful way to define and validate object schemas. In React applications, Yup is often used alongside form libraries like [Formik](https://github.com/jquense/yup) to streamline form validation. Yup allows developers to create complex validation schemas using a simple, declarative syntax, enabling robust and reusable validation logic across forms.

## Setting Up Yup

To start a new React app, check out the [documentation](https://react.dev/learn/start-a-new-react-project) for guidance. Then, in your terminal, install Yup using this command:

```bash
npm install yup
```

Make a new file called `UserValidation.js` in the `src` folder. This file will have a schema that holds validation rules.

### Creating Validation Schema

Yup simplifies the process of defining validation rules for your data through schema objects. These schemas describe the structure of your data and the rules each field must follow. For instance, when validating a user registration form, you specify rules for fields such as name, email, and password.

To get started, you need to import the `yup` dependency. Then, create a schema object named `userSchema` and export it for use in other components.

Initialize this schema using Yup's `object` and `shape` methods. `yup.object()` creates a new schema object, while `.shape({...})` defines the structure and validation rules.

Each field in the `shape` object has its own validation rules:

The `name` field:

* `yup.string()`: Specifies that it should be a string.
    
* `.required()`: Indicates that it must not be empty.
    

The `email` field:

* `yup.string()`: Specifies that it should be a string.
    
* `.email()`: Ensures it contains a valid email address.
    
* `.required()`: Indicates that it must not be empty.
    

The `password` field:

* `yup.string()`: Specifies that it should be a string.
    
* `.min(4)`: Ensures the password is at least 4 characters long.
    
* `.max(10)`: Ensures it is no more than 10 characters long.
    
* `.required()`: Indicates that it must not be empty.
    

```javascript
import * as yup from "yup";

// define the schema
export const userSchema = yup.object().shape({
  name: yup.string().required(),
  email: yup.string().email().required(),
  password: yup.string().min(4).max(10).required(),
});
```

### Schema Structure and Data Types

Yup supports various data types and allows you to structure schemas to match your data model. Common data types include:

* **Yup.string()**: Validates string values.
    
* **Yup.number()**: Validates numeric values.
    
* **Yup.boolean()**: Validates boolean values.
    
* **Yup.date()**: Validates date values.
    
* **Yup.array()**: Validates arrays of values.
    
* **Yup.object()**: Validates nested objects.
    

### Common Validation Methods and Options

Yup offers various ways to customize validation rules and error messages. Here are some common validation methods and options:

* `.required(message)`: Ensures the field is filled out.
    
* `.min(limit, message)`: Sets a minimum length or value requirement.
    
* `.max(limit, message)`: Sets a maximum length or value requirement.
    
* `.email(message)`: Validates that the input follows a valid email format.
    
* `.url(message)`: Validates that the input is a valid URL.
    
* `.matches(regex, message)`: Checks if the input matches a specific pattern defined by a regular expression.
    
* `.oneOf(array, message)`: Ensures the input matches one of the provided values.
    
* `.test(name, message, testFunction)`: Allows custom validation logic using a provided test function.
    

## Integrating Yup with React Forms

You can easily add dynamic Yup validation to your React form and display error messages using the `formik` library. Formik makes managing form state and validation in React much simpler. Start by installing `formik` with the following command:

```bash
npm install formik
```

Modify `App.js` to integrate Formik and import the `userValidation` schema:

```javascript
import { useFormik } from 'formik';
import { userSchema as userValidation } from './UserValidation';
```

First, let's create a `TextInput` component that you can reuse. This component will handle everything related to a text input field, including rendering, form state management, and displaying validation errors using Formik. It requires three props: `label`, `name`, and `formik`.

Inside this component, we'll define an `input` element with specific attributes:

* `type='text'`: Indicates that it's a text input field.
    
* `name={name}`: Associates the input with the form field's name for Formik to track.
    
* `placeholder={label}`: Uses the provided label prop as the placeholder text.
    
* `onChange={formik.handleChange}`: Updates the form state in Formik when the input value changes.
    
* `onBlur={formik.handleBlur}`: Marks the field as "touched" when the input loses focus, which helps in showing validation errors only after user interaction.
    
* `value={formik.values[name]}`: Sets the current value of the input field from Formik's state.
    

Finally, we'll conditionally display an error message if the field has been touched (`formik.touched[name]`) and if there's an error (`formik.errors[name]`).

```javascript
const TextInput = ({ label, name, formik }) => (
  <div>
    <input
      type='text'
      name={name}
      placeholder={label}
      onChange={formik.handleChange}
      onBlur={formik.handleBlur}
      value={formik.values[name]}
    />
    {formik.touched[name] && formik.errors[name] && (
      <div style={{ color: 'red' }}>{formik.errors[name]}</div>
    )}
  </div>
);
```

Using the `TextInput` component streamlines our form code, making it cleaner and easier to read. Instead of multiple lines for each input field, we condense it to a single line by passing the required props for state and validation handling dynamically.

### Linking Yup validation with form inputs

Firstly, in the `App` component initialize Formik using the `useFormik` hook. This hook requires three properties: `initialValues`, `validationSchema`, and an `onSubmit` handler.

The `initialValues` object sets the starting values for the form fields: `name`, `email`, and `password`, all initially empty.

Next, the `validationSchema` defines the rules for validating the form fields. In our case, we've defined these rules in a separate file called `UserSchema.js`.

The `onSubmit` handler is an asynchronous function that determines what occurs when the form is submitted. Currently, it simply logs the form values to the console. In a real application, this function would typically handle the form submission, such as sending the data to a server.

```javascript
function App() {
  const formik = useFormik({
    initialValues: {
      name: '',
      email: '',
      password: ''
    },
    validationSchema: userSchema,
    onSubmit: async (values) => {
      console.log(values);
    },
  });
  return (
    <div></div>
  );
}

export default App;
```

When submitting the form, it's processed through the `formik.handleSubmit` method. Within the `form` element, there are three `TextInput` components. These components are designed to minimize redundancy. Each `TextInput` includes a `formik={formik}` prop, which is essential for linking every input field to the Formik form instance.

```jsx
return (
  <div className='App'>
    <form onSubmit={formik.handleSubmit}>
      <TextInput label="Name.." name="name" formik={formik} />
      <TextInput label="email@gmail.com" name="email" formik={formik} />
      <TextInput label="password123" name="password" formik={formik} />
      <input className='button' type='submit' />
    </form>
  </div>
);
```

In the return component, utilize the `formik.handleSubmit` method to handle the form submission. Within the `<form>` element, define three `<TextInput>` components, each representing an input field for 'Name', 'Email', and 'Password'. To avoid redundancy, the `formik` prop is passed to each `<TextInput>` component, ensuring a connection to the Formik form instance.

```jsx
return (
  <div className='App'>
    <form onSubmit={formik.handleSubmit}>
      <TextInput label="Name.." name="name" formik={formik} />
      <TextInput label="email@gmail.com" name="email" formik={formik} />
      <TextInput label="password123" name="password" formik={formik} />
      <input className='button' type='submit' />
    </form>
  </div>
);
```

We've achieved form input validation using Yup and dynamically showcased error messages with Formik, as illustrated in the image below.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1716648601679/1087f372-6e4e-4c38-b6fb-98a4eaec5753.gif align="center")

## Conclusion

React form validation becomes straightforward and efficient with Yup and Formik. These tools work together to define validation rules and seamlessly integrate them into React forms. By doing so, developers can easily manage validation logic and offer immediate feedback to users, ensuring data accuracy and enhancing the user experience. This approach simplifies the creation of robust and user-friendly forms in React applications, leading to improved development efficiency and user satisfaction.
