How to Use Formik and Yup in Your React Project
Tags: react, frontend, javascript, tutorial
Published: 2023-08-21 22:15:37

####For my TLDR people skip to the TLDR section.

###Intro

Forms in React can be complex and tedious especially when working with controlled forms. Controlling state, adding validations, and handling submits can be a hassle when you have multiple form entries. Thankfully, libraries like Formik and Yup can help you add these features in a way that's simple and clean. So, let’s talk about how to use them.

>**Formik**
“Formik is a popular open-source library for building and processing form data in React applications” – [freecodecamp.org](https://www.freecodecamp.org/news/build-react-forms-with-formik-library/#:~:text=What%20is%20Formik%3F,a%20React%20application%20more%20enjoyable)

>**Yup**
“Yup is a schema builder for runtime value parsing and validation” – [npmjs.com](https://www.npmjs.com/package/yup)

###Set up 
**1. Set up your React Project**
I’m assuming most of you are already past this step but if not, you want to create your React project. You can follow along with the docs [here](https://create-react-app.dev/docs/getting-started/), it’s fairly simple and straightforward.

**2. Installing Formik and Yup**
To install formik and yup, you just need to run the command in your terminal: `npm install formik yup`. Once those dependencies finish installing you’re pretty much ready to use them.

**3. Create a form**
Once again, I’m assuming most of you are already passed this step. But just in case, here is a [link](https://www.youtube.com/watch?v=IkMND33x0qQ) to a great tutorial on how to make React controlled forms.

###Using Formik and Yup
**1. Import Formik**
At the top of the React component you want to use Formik in, you need to import it before you can use Formik.

```jsx
import React from 'react';
import { useFormik } from 'formik';

const MyForm = () => {
// Your form logic will go here
};

export default MyForm;
```

**2. Import Yup**
For Yup we have 2 different options. Since Yup helps with data validation it creates a schema. We can write this schema in the same component or we can write it in another file and import it. Both have their pros and cons but in general if you have multiple schemas it’s probably in your best interest to create a separate file. To do this, you first want to create a new folder in your `src` folder called schemas. In your schemas folder you want to create a JSX file (most people would just call it `index.jsx`). In your `index.jsx` file, you want to import Yup just like this: `import * as yup from 'yup'`. We don’t have schemas yet but we’ll cover that later when it becomes applicable. 

###Application
**1. Prefix**
For demonstration, I’m going to make a simple sign up form which includes a username and password. In your project you can build upon these ideas no matter how many inputs your form has. Here is what my form would look like if I were to build it in React without formik or yup:

```jsx
import React, { useState } from "react";

function SignupForm () {
    const [username, setUsername] = useState("")
    const [password, setPassword] = useState("")

    function handleSubmit(e) {
        e.preventDefault();
        fetch(//your promise)
    }   

    return (
        <form autoComplete="off" onSubmit={handleSubmit}>
            <label>Username</label>
            <input 
                type="text"
                id="username"
                placeholder="Enter your username..."
                value={username}
                onChange={(e) => setUsername(e.target.value)}
            />
            <label>Password</label>
            <input 
                type="password"
                id="password"
                placeholder="Enter your password..."
                value={password}
                onChange={(e) =>setPassword(e.target.value)}
            />
            <button type="submit">
                Signup
            </button>
        </form>
    )
};

export default LoginForm;
```

**2. Creating a Schema**
In our `index.jsx` file we created in the schema folder, let’s first create a schema or some validations we want to use in our form. Our file should look like this:

```jsx
import * as yup from "yup"
```

To define our schema we want to type this:

```jsx
export const schema = yup.object().shape({})
```

`export` will allow us to export this schema to any component it’s needed. Inside `.shape({})` we are going to define our validations. Here is a simple validation schema:

```jsx
export const schema = yup.object().shape({
    username: yup.string("Please enter a valid name").required("Required"),
    password: yup.string().min(5).required("Required"),
})
```

For username we are saying that it needs to be a string with `.string()` and it cannot be empty (or null) with `.required()`. Inside of those methods we type an error message as a string.
For password we are once again saying that it needs to be a string with `.string` and it cannot be empty (or null) with `.required()`. We also state that the password needs to be a minimum length of 5.

Our `index.jsx` will look something like this:

```jsx
import * as yup from "yup"

export const basicSchema = yup.object().shape({
    username: yup.string("Please enter a valid name").required("Required"),
    password: yup.string().min(5).required("Required"),
})
```

**3. Incorporating Formik**
To use formik we declare it as so:

```jsx
const formik = useFormik({}) 
```
We can destructure formik to access certain elements. First let’s focus on state management. Let’s destructure our formik variable:
 
```jsx
const { values, handleChange, handleSubmit } = useFormik({}) 
```
There are more elements, but these are the basic ones we need. For state management, we no longer need `useState`. It’s now replaced by `values` and `handleChange`. Let's make our `values`:

```jsx 
const { values, handleChange, handleSubmit} = useFormik({
    initialValues: {
        username: "",
        password: "",
    },
})
```

Then change our form as so:

```jsx
<label>Username</label>
<input 
    type="text"
    id="username"
    placeholder="Enter your username..."
    value={values.username}
    onChange={handleChange}
/>
<label>Password</label>
<input 
    type="password"
    id="password"
    placeholder="Enter your password..."
    value={values.password}
    onChange={handleChange}
/>
```

After we handle state management we need to add our schema here. Since we created a separate file, all we have to do is import and call it for the `validationSchema`:

```jsx
import { basicSchema } from '../schemas'
// our component 
const { values, handleChange, handleSubmit} = useFormik({
    initialValues: {
        username: "",
        password: "",
    },
    validationSchema: basicSchema, 	
})
```

Now let's add `onSubmit` function underneath `validationSchema`: 

```jsx
// our component 
const { values, handleChange, handleSubmit} = useFormik({
    initialValues: {
        username: "",
        password: "",
    },
    validationSchema: basicSchema, 
    onSubmit: (values) => {
	fetch(// your promise)
    },
})
```

You could also keep the `onSubmit` function separate like this:

```jsx
const onSubmit = (values) => {
	fetch(// your promise)

const { values, handleChange, handleSubmit} = useFormik({
    initialValues: {
        username: "",
        password: "",
    },
    validationSchema: basicSchema, 
    onSubmit,
})
```
###Conclusion 
Formik and Yup are great tools to help make React forms more responsive and easier to manage. With state management, validations, and a cleaner syntax they can help enhance your project. For more information on [Formik](https://formik.org/docs/overview) or [Yup](https://github.com/jquense/yup/tree/pre-v1) check out the documentation.

###TDLR 
```jsx
//imports
import React from "react";
import { useFormik } from 'formik';
import { basicSchema } from '../schemas';

//form component
function SignupForm() {

//formik 
    // declare and destucture 
    const { values, handleChange, handleSubmit} = useFormik({
        // setup values
        initialValues: {
            username: "",
            password: "",
        },
        // setup schema/validation
        validationSchema: basicSchema, 
        // submit function
        onSubmit: (values) => {
	        fetch(// your promise)
        },
    })
    //form
    return (
        <label>Username</label>
        <input 
            type="text"
            id="username"
            placeholder="Enter your username..."
            value={values.username}
            onChange={handleChange}
        />
        <label>Password</label>
        <input 
            type="password"
            id="password"
            placeholder="Enter your password..."
            value={values.password}
            onChange={handleChange}
        />
    )
}

//schemas folder => index.jsx 
import * as yup from "yup"

//schema for formik
export const basicSchema = yup.object().shape({
    // add validation for each value
    username: yup.string("Please enter a valid name").required("Required"),
    password: yup.string().min(5).required("Required"),
})

```

###Sources
- [https://www.freecodecamp.org/news/build-react-forms-with-formik-library/#:~:text=What%20is%20Formik%3F,a%20React%20application%20more%20enjoyable](https://www.freecodecamp.org/news/build-react-forms-with-formik-library/#:~:text=What%20is%20Formik%3F,a%20React%20application%20more%20enjoyable)
- [https://www.npmjs.com/package/yup](https://www.npmjs.com/package/yup)
- [https://create-react-app.dev/docs/getting-started/](https://create-react-app.dev/docs/getting-started/)
- [https://www.youtube.com/watch?v=IkMND33x0qQ](https://www.youtube.com/watch?v=IkMND33x0qQ)
- [https://formik.org/docs/overview](https://formik.org/docs/overview)
- [https://github.com/jquense/yup/tree/pre-v1](https://github.com/jquense/yup/tree/pre-v1)