Formik: Building forms in react Step by Step
Formik : Building forms in react with formik

Formik: Building forms in react Step by Step

Dead Simple Chat Team

Table of Contents

In this article we are going to learn about formik. A  form library in React. We will learn how to build forms with formik in react with different examples and in a step by step manner

Step1 : Formik: Installation and setup

Open your react application or if you are just starting our create a new react application with create-react-app or with Next.js like

npx create-react-app
npx create-next-app

Next, open your terminal and install the dependencies

npm install formik yup reactstrap bootstrap

Yup is a validation library and reactStrap is a css framework for beautification (bootstrap for react)

Now that we have installed the dependencies, let us open the App.js file and import our dependencies

If you are looking for a React Native Chat SDK, you can consider DeadSimpleChat React Native SDK

import React from 'react';
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';
import { Container, Button, FormGroup, Label } from 'reactstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
importing dependencies

before creating a form let us create a validation schema using YUP. If you are not interested in validation simply skip this step

const validationSchema = Yup.object().shape({
  username: Yup.string().required('Username is required'),
  email: Yup.string().email('Invalid email format').required('Email is required'),
  password: Yup.string().min(6, 'Password must be at least 6 characters').required('Password is required'),
});

Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.

Step 2 Set the initial values for the form

Let us set the initial values for the form

You can set initial values by defining an Object

const initialValues = {
  username: '',
  email: '',
  password: '',
};

Dead Simple Chat allows you to easily add Chat to any React Application using powerful Javascript Chat SDK.

Step 3: Create a structure for the form and a Formik component

Lets us wrap the DOM elements in a formik component and pass teh validation schema and the initial values for the form

function App() {
  return (
    <Container>
      <h1>Example of a Formi FOrm</h1>
      <Formik
        initialValues={initialValues}
        validationSchema={validationSchema}
        onSubmit={(values, { setSubmitting }) => {
          setTimeout(() => {
            alert(JSON.stringify(values, null, 2));
            setSubmitting(false);
          }, 400);
        }}
      >
        {({ isSubmitting }) => (
          <Form>
            {/*add the form elements here*/}
          </Form>
        )}
      </Formik>
    </Container>
  );
}

Step 4: Add form fields and submit button

Add the form fields and the submit button to the form that we created above like so

<FormGroup>
  <Label for="username">Username:</Label>
  <Field type="text" name="username" id="username" className="form-control" />
  <ErrorMessage name="username" component="div" className="text-danger" />
</FormGroup>
<FormGroup>
  <Label for="email">Email:</Label>
  <Field type="email" name="email" id="email" className="form-control" />
  <ErrorMessage name="email" component="div" className="text-danger" />
</FormGroup>
<FormGroup>
  <Label for="password">Password:</Label>
  <Field type="password" name="password" id="password" className="form-control" />
  <ErrorMessage name="password" component="div" className="text-danger" />
</FormGroup>
<Button type="submit" color="primary" disabled={isSubmitting}>
  {isSubmitting ?'Submitting...' : 'Submit'}
</Button>

Step 5: Adding the OnSubmit functionality

In this step let us add the onSubmit functionality

onSubmit={(values, { setSubmitting }) => { setTimeout(() => { alert(JSON.stringify(values, null, 2)); setSubmitting(false); }, 400); }}

Step 6 Styling the form

We can style our form to look good using the bootstrap library that we imported earlier. This is complementary and not related to formik

.container {
  max-width: 600px;
  margin: 50px auto;
}

.form-group {
  margin-bottom: 15px;
}

Step 7: Running the app

Now that we have built the formik application let us run it.

Open your terminal and write the below code:

npm start

What is formik?

Formik is a react library for creating forms. It is small and easy to work with. Formik consists of React Hooks and components that solves these three problems related to form

  • Storing and retriving values from state
  • error messaging and form validation
  • handling form submission

Formik makes testing, refactoring and maintaining the forms very easy by colocation all the above functionality in one place

Simple Formik Examples

Let us consider a simple example of a newsletter form sign up. We will be building a newsletter sign up for a blog with just one field that is email.

We can write this with a few lines of code and formik

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

const SignupForm = () => {
    // a submit funtion and initial form values are needed to be passed to the useFormik() hook.
    //The submit function will be called when the form is submitted
  const formik = useFormik({
    initialValues: {
      email: '',
    },
    onSubmit: values => {
      alert(JSON.stringify(values, null, 2));
    },
  });
  return (
    <form onSubmit={formik.handleSubmit}>
      <label htmlFor="email">Write Email Address</label>
      <input
        id="email"
        name="email"
        type="email"
        onChange={formik.handleChange}
        value={formik.values.email}
      />

      <button type="submit">Submit</button>
    </form>
  );
};
simple newletter form sign up

We pass our initialValues and a submission function to the useForm hook. The hook returns form state and helper methods in a var called formik

These are the helper methods that are returned and are important

  • handleSubmit: submission handler
  • handleChange: change handler to pass to each of <input> <select> and <textarea>
  • values: forms current values

We can pass each of these to their respective props. We now have a working form powered by formik

Instead of managing everything related to forms and writing our own custom event hanlers we can just useFormik()

This is neat but with just one input it is unclear what benefits the formik offers. Let us consider an example with 3 inputs. An input for user's first name another for user's last name and the last one for a user's email

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

const SignupForm = () => {
  // note that we need to initialize all the form fields with values these could be empty string. If we don't do this react will give us errors
    
  const formik = useFormik({
    initialValues: {
      firstName: '',
      lastName: '',
      email: '',
    },
    onSubmit: values => {
      alert(JSON.stringify(values, null, 2));
    },
  });
  return (
    <form onSubmit={formik.handleSubmit}>
      <label htmlFor="firstName">First Name</label>
      <input
        id="firstName"
        name="firstName"
        type="text"
        onChange={formik.handleChange}
        value={formik.values.firstName}
      />

      <label htmlFor="lastName">Last Name</label>
      <input
        id="lastName"
        name="lastName"
        type="text"
        onChange={formik.handleChange}
        value={formik.values.lastName}
      />

      <label htmlFor="email">Email Address</label>
      <input
        id="email"
        name="email"
        type="email"
        onChange={formik.handleChange}
        value={formik.values.email}
      />

      <button type="submit">Submit</button>
    </form>
  );
};
formik with three values

Let us study the code further

  1. We can use the same changeHandler function for each HTML input that is the handleChange
  2. The property that we defined in the initialValues have the same id and name as the HTML attribute for each input
  3. We can accesse the fields value like (email - > formail.values.email)

Validation

Next let us add validation to our forms that would tell the users that there is something missing in the form or that they have made some mistake while filling out the form

If you want to use the browsers in-built validation just add the required in the element like

<input required />

or specify min and max lengths, or add a regex pattern to control user behaviour

There are som eproblems with the built in HTML validation that the formik wants to solve these are

  • HTML validation doesn't work in react native
  • Its hard to show custom error messages in the built in HTML form

Formik keeps track of a form's values and validation as well as error messages. To validate with formik create a function for validation and pass validate  function to the useFormik() hook

If the error is there the custom validation function should produce and error object matching the initialValues

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

// the custom validation object must return a object with key value pairs 
//with matching shape (similar)  to the values/initialValues

const validate = values => {
  const errors = {};
  if (!values.firstName) {
    errors.firstName = 'Required';
  } else if (values.firstName.length > 15) {
    errors.firstName = 'Must be 15 characters or less';
  }

  if (!values.lastName) {
    errors.lastName = 'Required';
  } else if (values.lastName.length > 20) {
    errors.lastName = 'Must be 20 characters or less';
  }

  if (!values.email) {
    errors.email = 'Required';
  } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
    errors.email = 'Invalid email address';
  }

  return errors;
};

const SignupForm = () => {
    //initial form values should be passed to the useFormik() hook. 
    // A validate function will be called when form values change and submit 
    //funtion will be called when the form is submitted
  const formik = useFormik({
    initialValues: {
      firstName: '',
      lastName: '',
      email: '',
    },
    validate,
    onSubmit: values => {
      alert(JSON.stringify(values, null, 2));
    },
  });
  return (
    <form onSubmit={formik.handleSubmit}>
      <label htmlFor="firstName">First Name</label>
      <input
        id="firstName"
        name="firstName"
        type="text"
        onChange={formik.handleChange}
        value={formik.values.firstName}
      />
      {formik.errors.firstName ? <div>{formik.errors.firstName}</div> : null}

      <label htmlFor="lastName">Last Name</label>
      <input
        id="lastName"
        name="lastName"
        type="text"
        onChange={formik.handleChange}
        value={formik.values.lastName}
      />
      {formik.errors.lastName ? <div>{formik.errors.lastName}</div> : null}

      <label htmlFor="email">Email Address</label>
      <input
        id="email"
        name="email"
        type="email"
        onChange={formik.handleChange}
        value={formik.values.email}
      />
      {formik.errors.email ? <div>{formik.errors.email}</div> : null}

      <button type="submit">Submit</button>
    </form>
  );
};

formik.errors is populated by the custom validation function

By default Formik validates after each keystroke, input fields blur event and prior to submission when the submit button is pressed

The onSubmit function is called when the validation is passed by the formik

Visited fields

Next we need to implement visited fields as the formik is throwing errors all over the place when the form first loads

to implement the visited fields, we will need the formik's touched object. The formik stores the data on touched Object and also mirrors the shape of values / initialValues

The key /value pairs of touched are field names and boolean true or false

To use the touched property we pass the formik.handleBlur to each input onBlur prop

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

const validate = values => {
  const errors = {};

  if (!values.firstName) {
    errors.firstName = 'Required';
  } else if (values.firstName.length > 20) {
    errors.firstName = 'less than 20 char';
  }

  if (!values.lastName) {
    errors.lastName = 'Required';
  } else if (values.lastName.length > 20) {
    errors.lastName = 'less than 20 char';
  }

  if (!values.email) {
    errors.email = 'Required';
  } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
    errors.email = 're type the email address';
  }

  return errors;
};

const SignupForm = () => {
  const formik = useFormik({
    initialValues: {
      firstName: '',
      lastName: '',
      email: '',
    },
    validate,
    onSubmit: values => {
      alert(JSON.stringify(values, null, 2));
    },
  });
  return (
    <form onSubmit={formik.handleSubmit}>
      <label htmlFor="firstName">First Name</label>
      <input
        id="firstName"
        name="firstName"
        type="text"
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
        value={formik.values.firstName}
      />
      {formik.errors.firstName ? <div>{formik.errors.firstName}</div> : null}

      <label htmlFor="lastName">Last Name</label>
      <input
        id="lastName"
        name="lastName"
        type="text"
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
        value={formik.values.lastName}
      />
      {formik.errors.lastName ? <div>{formik.errors.lastName}</div> : null}

      <label htmlFor="email">Email Address</label>
      <input
        id="email"
        name="email"
        type="email"
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
        value={formik.values.email}
      />
      {formik.errors.email ? <div>{formik.errors.email}</div> : null}

      <button type="submit">Submit</button>
    </form>
  );
};

Conclusion

In this article we wrote about the formik form validation and how you can use it in your website or react native application

formik makes building forms an easy task. It is also a very small library and doesn't bloat your application

It comes with Yup schema validation and other beautiful features

Thank you for reading