Best way to handle React forms with Formik

Best way to handle React forms with Formik

Introduction

Today we will use React.js with Fomik to create web application forms. Forms are a complicated part of our application; to ease this part, we use React and Fomik.

Prerequisites

Before you start with the tutorial you need to know about React.js

What is Formik?

Formik is a form management library that provides components and hooks to ease the process of creating React forms. Formik takes care of form states, validation, and error handlers for you, making it easy to collect and store user data.

Formik has two options for handling forms:

  1. Hook-based Form → useFormik()
  2. Component-based Form → <Formik>

Note: You can’t use Hook and Component together.

Install Formik in your application

npm i fomik

First, we use the Hook base form

useFormik() is a custom Formik hook that will return all Formik states and helpers.

1. Import and declare the hook

import the hook

import { useFormik } from "formik";

2. Setup the initial values, form submission, and form validation.

Setup the initial values Object

Your input elements values are saved in this initialValues object.

const formik = useFormik({
  //initial input values
    initialValues: {
      name: "",
      email: "",
      password: "",
    },
  });

Setup the form validation function

Validate the form and show the error messages

const formik = useFormik({
  //initial input values
    initialValues: {
      name: "",
      email: "",
      password: "",
    },
   // form validation
    validate: (values) => {
      let errors = {};
      if (!values.name) errors.name = "Required";
      if (!values.email) errors.email = "Required";
      if (!values.password) errors.password = "Required";
      return errors;
    },
  });

Validate function values come from the initialValues object.

Setup the form submission function

In the onSubmit function, you can perform all the form submission processes and other things.

const formik = useFormik({
   //initial input values
    initialValues: {
      name: "",
      email: "",
      password: "",
    },
    // form validation
    validate: (values) => {
      let errors = {};
      if (!values.name) errors.name = "Required";
      if (!values.email) errors.email = "Required";
      if (!values.password) errors.password = "Required";
      return errors;
    },
    //submit form data
    onSubmit: (values) => {
      console.log(values);
    },
  });

onSubmit function values come from the initialValues object.

3. Setup the JSX

useFormik() hook has multiple functions like handleSubmit, getFieldProps etc.

The handleSubmit function handles the form submission.

return (
  <>
    <form onSubmit={formik.handleSubmit}>

    </form>
 </>
);

Add Input element

getFieldProps handle your onChange function, and also values attribute, etc.

Note: You don’t need to add the onChange function and the value attribute.

return (
 <>
    <form onSubmit={formik.handleSubmit}>
        <input
          type="name"
          id="name"
          {...formik.getFieldProps("name")}
        />
    </form>
 </>
);

getFieldPropsfunction contains the value attribute and the onChange function handler

Implementing the error message

return (
 <>
    <form onSubmit={formik.handleSubmit}>
        <input
          type="name"
          id="name"
          {...formik.getFieldProps("name")}
        />
        {/* error message */}
        {formik.touched.name ? ( <div>{formik.errors.name}</div> ) : null}

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

Full code:

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

const Form = () => {
  //custom formik hook
  const formik = useFormik({
    //initial input values
    initialValues: {
      name: "",
      email: "",
      password: "",
    },
    //setup form validation & Error message
    validate: (values) => {
      let errors = {};
      if (!values.name) errors.name = "Required";
      if (!values.email) errors.email = "Required";
      if (!values.password) errors.password = "Required";
      return errors;
    },
   //handle form submission
    onSubmit: (values) => {
      console.log(values);
    },
  });
  return (
    <>
      <form onSubmit={formik.handleSubmit}>

        <input
          type="name"
          id="name"
          {...formik.getFieldProps("name")}
        />
        {/*Error Message*/}
        {formik.touched.name ? ( <div>{formik.errors.name}</div> ) : null}


        <input
          type="email"
          id="email"
          {...formik.getFieldProps("email")}
        />
        {/*Error Message*/}
        {formik.touched.email ? ( <div>{formik.errors.email}</div> ) : null}

        <input
          type="password"
          id="password"
          {...formik.getFieldProps("password")}
        />
        {/*Error Message*/}
        {formik.touched.password ? ( <div>{formik.errors.password}</div> ) : null}

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

export default Form;

Component-based Form

Component-based Formik gives you lots of built-in components for handling the form. Components like: Formik, Form, Field, etc.

Step 1: Import the Components

Import the components at the top of the page.

import { Formik, Form, Field, ErrorMessage } from "formik";

Step 2: Setup initial values, form submission, and form validation

First setup initialValues

We need to create an Object name initialValues, and then we need to add all the input fields name attributes name: name, email, and password.

//handle and save the input values
const initialValues = {
  name: "",
  email: "",
  password: "",
};

Second is the Form submission.

In the onSubmit function, you can perform all the form submission processes and other things.

Create a function with the name onSubmit, then declare the values parameter in the function, and now you can see the form values on the console.

const onSubmit = (values) => {
  //values come from the initialValues Object
  console.log(values);
};

Third, setup the Form Validation functions

Create a function with the name validate, then declare the name value on the function parameter.

Under the function, create an error variable, then run a condition, and then return the error variable.

const validate = (value) => {
  let error;
  //if the value is empty. 
  if (!value) error = "Required";
  return error;
};

Step 3: Declare the Components

First, we need to declare the Formik component.

The Formik component handles all the input value passes and the form submissions.

The Formik component requires initialValues and the onSubmit as props, we already created the initialValues Object and the onSubmit function.

return (
    <Formik initialValues={initialValues} onSubmit={onSubmit}>

    </Formik>
  );

Second, declare the Form component under the Formik component.

return (
    <Formik initialValues={initialValues} onSubmit={onSubmit}>
       <Form>

       </Form>
    </Formik>
  );

Third, declare the Field component under the Form component.

The Field component is just like the input element.

The Field component required type, name, id, validate, as props. We have already created the validate function.

Note: You don’t need to add the onChange function.

return (
    <Formik initialValues={initialValues} onSubmit={onSubmit}>
       <Form>
         <Field
           type="name"
           name="name"
           id="name"
           validate={validate}
         />
       </Form>
    </Formik>
  );

Forth, declare the ErrorMessage component below the Field component.

The ErrorMessage component handles the Field component errors.

The ErrorMessage component requires a name, and component as props, the name props is the same as your Filed component name.

return (
    <Formik initialValues={initialValues} onSubmit={onSubmit}>
       <Form>
         <Field
           type="name"
           name="name"
           id="name"
           validate={validate}
         />
        {/* show the error message */}
        <ErrorMessage name="name" component='div' />
       </Form>
    </Formik>
  );

Last, add a Button for Form Submission

<button type="submit">Submit</button>

Full Code

import React from "react";
import { Formik, Form, Field, ErrorMessage } from "formik";

const Component_form = () => {
  //handle and save the input values
  const initialValues = {
    name: "",
    email: "",
    password: "",
  };
  //Form Submit function
  const onSubmit = (values) => {
    //values come from the initialValues Object
    console.log(values);
  };
  //Form Validation function
  const validate = (value) => {
    let error;
    if (!value) error = "Required";
    return error;
  };
  return (
    <Formik initialValues={initialValues} onSubmit={onSubmit}>
      <Form>
        {/* input filed */}
        <Field type="name" name="name" id="name" validate={validate} />
        {/* show the error message */}
        <ErrorMessage name="name" component="div" />

        <Field type="email" name="email" id="email" />
        <ErrorMessage component="div" name="email" />

        <Field type="password" name="password" id="password" />
        <ErrorMessage name="password" />

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

export default Component_form;

Summary

Formik is an excellent library for handling forms and is also easy to use. They will give you multiple options for managing forms. If you don’t want to use custom coding you can easily use Formik for your application.