Type to generate custom UI components with AI

Type to generate UI components from text

OR

Browse thousands of MUI, Tailwind, React components that are fully customizable and responsive.

Explore Components

Building Amazing Forms in React with Formik

Building forms in React can be a complex task, especially as your application grows in size and complexity. Managing form state, validation, and user interactions can become a challenge. This is where libraries like Formik come into play, offering a streamlined and efficient way to handle forms in a React application.

Introducing Formik

Formik is a popular form management library that simplifies the process of building forms and handling them in React. It provides a set of abstractions and utilities that make the form development process more intuitive and less error-prone. Whether you are an experienced React developer or a beginner, Formik can significantly improve your form-building experience.

One of the pivotal aspects of Formik is its ability to manage form state seamlessly. The traditional approaches often involve state variables for each form field, leading to an error-prone and cluttered codebase. Formik introduces a centralized form state, bringing order to chaos. This not only enhances code readability but also facilitates efficient state management, paving the way for a better-maintained codebase.

As we progress through this exploration of Formik, keep in mind that this library not only simplifies the form development process but also promotes code consistency and reusability. It is a very powerful ally in the React ecosystem, and by the end of this article, you will not only understand how to use Formik effectively but also appreciate its role in elevating your applications to new heights of user satisfaction and efficiency. Let us embark on this journey of mastering form building with Formik in React!

Form Validation

validation

Form validation is a very important aspect of web development that ensures data entered into a form meets specified criteria before submission. It helps to improve user experience, prevent malicious inputs and maintain data integrity.

Validation can be performed on the client side using JavaScript for real-time feedback and also on the server side to ensure consistency and security. Common validation types include required fields, length constraints, numeric formats, email addresses, and more. Implementing thorough form validation is essential for creating robust and user-friendly web applications.

Why do we Need to Validate Forms?

Imagine a helpful friend double-checking everything you write on a job application letter so that things go smoothly and nothing goes wrong, this is how form validations work. They are essential for several reasons.

  • Security: Validation on the server side is crucial for preventing malicious inputs and protecting against potential security threats like cross-site scripting and SQL injection.

  • User Experience: Validating forms on the client side helps to provide real-time feedback, helping to ensure smooth user inputs and improving overall user experience.

  • Data Integrity: Validations ensure that only well-formatted and accurate data is submitted, preventing inconsistencies and errors across the database.

PS: Engineers waste time building and styling components when working on a project, writing repetitive markup adds time to the project and is a mundane, boring task for engineers. PureCode.ai uses AI to generate a large selection of custom, styled UI components for different projects and component types.

What is Formik?

formik

Formik is a widely adopted and robust open-source library designed to streamline the often intricate process of managing forms in React applications. As forms play an important role in user interactions with web applications, Formik reduces the complexities associated with form development by providing a comprehensive set of components, utilities and tools.

//  traditional method for react form management 

import { useState } from "react";

function InputForm() {
  const [input1, setInput1] = useState("");
  const [input2, setInput2] = useState("");

  const handleInputChange = (event) => {
    const { name, value } = event.target;
    if (name === "input1") {
      setInput1(value);
    } else if (name === "input2") {
      setInput2(value);
    }
  };

  const handleSubmit = (event) => {
   // . . .
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="input1" value={input1} onChange={handleInputChange} />
      <input name="input2" value={input2} onChange={handleInputChange} />
      <button type="submit">Submit</button>
    </form>
  );
}

export default InputForm;

As seen above, the annoying traditional method of form management requires us to create a single or universal `useState()` for each form field. An event listener is added to each field and then triggering a method to individually update them.

Now, let us take a look at how formik handles this

<Formik
  onSubmit={(formData) => {
    console.log(formData);
  }}
>
  {({ isSubmitting }) => (
    <Form>
      <Field type="text" name="fullname" placeholder="Enter fullname" />
      <Field type="email" name="email" placeholder="Enter address" />
      <button type="submit">Submit</button>
    </Form>
  )}
</Formik>;

We can see that Formik has handled the stressful operations for us. All we had to do was import its component, our form data being readily available.

Why Should We Use Formik in React?

Some key features of Formik include:

  • Declarative Form Handling: Formik makes use of a declarative approach to manage form state, reducing the need for manual event handling and state management.

  • Form Submission: Formik handles form submissions, including asynchronous actions like API calls. It provides functions for submitting forms and handling the submission process.

  • Form Validation: It supports both asynchronous and synchronous form validation, allowing you to define validation rules easily.

  • Touched and Visited Tracking: Formik tracks whether a form field has been touched or visited, providing an advantage in flexible display of an error message and feedback

  • Field-Level Control: Formik also enables developers to have control over an individual form field, enabling dynamic interactions and behaviors

  • Compatibility with React Ecosystem: Formik offers high compatibility with React and other React libraries. It offers seamless integration with UI libraries like Material-UI.

Installing Formik

Setting up our React project

First, let us set up our React project

npx create-react-app my-app
cd my-app
npm start

Formik Installation

To install Formik in your React project, you can either use `npm` or `yarn`, depending on your package manager preference.

Using `npm`

npm install formik

Using `yarn`

yarn add formik

Importing Formik Properties

Once installation is complete, we can import Formik’ s components and use them in our application

import { Formik, Form, Field, ErrorMessage } from 'formik';
  • Form: The Form component is used to define the boundaries of your form. It wraps all the form-related elements such as input fields, buttons, and validation components. It also functions as the form submission handler and provides the necessary context for Formik to manage the form states.

    <Form>
    {/* Elements go in here */}
    </Form>
  • Field: The Field component is used to represent input elements within the form. Examples include elements like text, checkboxes, radio, buttons, etc.

    The `name` prop of `Field` corresponds to the key in the Formik `values` object, thereby establishing a connection between the field and the form’s state. Formik takes care of managing the state, handling changes, and validation for the form’s values.

    
                 <Field
                   type="text"
                   name="username"
                   placeholder="enter your username"
                 />
  • ErrorMessage: The Error message component is used to display validation error messages for a specific field. It automatically connects to the corresponding field’s name and displays the error message if validation fails. It also helps improve user experience by providing prompt feedback on incorrect or incomplete form input.

    <ErrorMessage name="username" component="div" />

These components work hand in hand to create a declarative and streamlined approach to building forms in React with Formik. They abstract away much of the boilerplate code associated with form handling, validation and error messages display making it easier for you to create robust and user-friendly forms in their React applications

Form Creation with Formik

Here is a code example of creating form input using Formik

import React from "react";
import { Formik, Form, Field, ErrorMessage } from "formik";
function App() {
 return (
   <div className="App">
     <center>
       <h1>Register a new account</h1>
       <Formik>
         {({ isSubmitting }) => (
           <Form>
             <Field
               type="text"
               name="fullname"
               placeholder="Enter your fullname"
             />
             <ErrorMessage name="fullname" component="div" />

             <Field
               type="email"
               name="email"
               placeholder="Enter email address"
             />
             <ErrorMessage name="email" component="div" />

             <Field type="password" name="password" />
             <ErrorMessage name="password" component="div" />

             <button type="submit" disabled={isSubmitting}>
               Submit
             </button>
           </Form>
         )}
       </Formik>
     </center>
   </div>
 );
}
export default App;

In the example above, we can see that the Formik component wraps around the form and gives us utilities like submission handling and form validation. Also, the Field component defines every form values such as the `email` , `password` , `fullname`. The errorMessage component then displays validation errors for each field.

We also see that the `isSubmitting` prop is passed to the render prop function. This is used to disable the submit button while the form is submitted.

Form Validation with Formik

In the creation of forms, it is important that we validate user inputs data to tackle errors. We will set the field’s initial values by passing the `initialValues` prop. We will set the values for fullname, email and password.

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

Now, let us validate form using Formik.

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

const MyForm = () => {
  const initialValues = {
    username: '',
    email: '',
    password: '',
  };

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

    if (!values.username) {
      errors.username = 'Username is required';
    } else if (values.username.length < 3) {
      errors.username = 'Username must be at least 3 characters';
    } else if (values.username.length > 15) {
      errors.username = 'Username must be at most 15 characters';
    }

    if (!values.email) {
      errors.email = 'Email is required';
    } else if (!/^S+@S+.S+$/.test(values.email)) {
      errors.email = 'Invalid email address';
    }

    if (!values.password) {
      errors.password = 'Password is required';
    }

    return errors;
  };

  const onSubmit = (values) => {
    // Handle form submission logic here
    console.log(values);
  };

  const errorStyle = {
    color: 'red',
    margin: '5px 0',
  };

  return (
    <Formik
      initialValues={initialValues}
      validate={validate}
      onSubmit={onSubmit}
    >
      <Form>
        <div>
          <label htmlFor="username">Username:</label>
          <Field
            type="text"
            id="username"
            name="username"
            placeholder="Enter your username"
          />
          <ErrorMessage name="username" component="div" style={errorStyle} />
        </div>

        <div>
          <label htmlFor="email">Email:</label>
          <Field
            type="email"
            id="email"
            name="email"
            placeholder="Enter your email"
          />
          <ErrorMessage name="email" component="div" style={errorStyle} />
        </div>

        <div>
          <label htmlFor="password">Password:</label>
          <Field
            type="password"
            id="password"
            name="password"
            placeholder="Enter your password"
          />
          <ErrorMessage name="password" component="div" style={errorStyle} />
        </div>

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

export default MyForm;

Step by step, let us go through the code.

Importing Dependencies

We started by importing the necessary dependencies from the React and Formik libraries.

Setting up Initial Form Values

The `initialValues` constant is an object that represents the initial state of the form. It includes the initial state of the form. It includes fields for username, email and password.

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

Form Validation Function

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

    if (!values.username) {
      errors.username = 'Username is required';
    } else if (values.username.length < 3) {
      errors.username = 'Username must be at least 3 characters';
    } else if (values.username.length > 15) {
      errors.username = 'Username must be at most 15 characters';
    }

    if (!values.email) {
      errors.email = 'Email is required';
    } else if (!/^S+@S+.S+$/.test(values.email)) {
      errors.email = 'Invalid email address';
    }

    if (!values.password) {
      errors.password = 'Password is required';
    }

    return errors;
  };

The `validate` function is responsible for validating the form fields based on certain criteria. The `username` field checks if it is empty, if it is less than 3 characters, or if it is more than 15 characters. For the `email` field, it checks if it is empty and if it matches a basic email format with a regular expression. The `password` field checks if it is empty.

Form Submission Function

  const onSubmit = (values) => {
    // Handle form submission logic here
    console.log(values);
  };

The `onSubmit` function acts as a placeholder for the logic that should be executed when the form is successfully submitted. In this example, the `onSubmit` function logs the form values to the console.

Form Submission Button

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

This simply triggers the onsubmit function.

Now, let us see the output of our code.

Note: additional CSS styling was applied to this output.

validation output

In the image above, we can see that once the submit button is clicked, validation is triggered and error messages appear if validation conditions are not met.

Form Submission Process in Formik

From the above code, we can see that Formik simply uses an `onSubmit` function to handle the form data whenever the submit button gets clicked.

const onSubmit = (values) => {
    // Handle form submission logic here
    console.log(values);
  };
//button triggering the submit function
<button type="submit">Submit</button>

Form Validation with Formik and Yup

Let’s talk about Yup.

Yup is one of the validation methods available. It is a library that simplifies the validation process by allowing developers to define validation schemas using a concise and expressive syntax. To get started, you need to install it in your React project.

npm install yup
# or
yarn add yup
  • Validation Schema: Yup supports validation for various data types such as strings, number, dates, and more. Creating basic validation schemas involves chaining methods to specify rules.

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

Now, let us create a form and validate using Yup.

import React from 'react';
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';

const MyForm = () => {
  const initialValues = {
    username: '',
    email: '',
    password: '',
  };

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

  const onSubmit = (values) => {
    // Handle form submission logic here
    console.log(values);
  };

  return (
    <Formik
      initialValues={initialValues}
      validationSchema={validationSchema}
      onSubmit={onSubmit}
    >
      <Form>
        <div>
          <label htmlFor="username">Username:</label>
          <Field
            type="text"
            id="username"
            name="username"
            placeholder="Enter your username"
          />
          <ErrorMessage name="username" component="div" style={{ color: 'red', marginTop: '5px' }} />
        </div>

        <div>
          <label htmlFor="email">Email:</label>
          <Field
            type="email"
            id="email"
            name="email"
            placeholder="Enter your email"
          />
          <ErrorMessage name="email" component="div" style={{ color: 'red', marginTop: '5px' }} />
        </div>

        <div>
          <label htmlFor="password">Password:</label>
          <Field
            type="password"
            id="password"
            name="password"
            placeholder="Enter your password"
          />
          <ErrorMessage name="password" component="div" style={{ color: 'red', 				     		marginTop: '5px' }} />
        </div>

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

export default MyForm;

Take a look at the code output.

validation with formik

Here is a YouTube tutorial to help you learn this concept better.

The useFormik Hook Method

The `useFormik` hook initializes Formik’s form state, handling form values, submissions, validation and other related functionalities.

Let us create a form and achieve validation once more using the useFormik hook method.

import React from 'react';
import { useFormik } from 'formik';
import * as Yup from 'yup';

const MyForm = () => {
  // useFormik hook sets up the form state and provides helpful functions
  const formik = useFormik({
    initialValues: {
      username: '',
      email: '',
      password: '',
    },
    // Validation rules defined using Yup
    validationSchema: Yup.object().shape({
      username: Yup.string()
        .required('Username is required')
        .min(3, 'Username must be at least 3 characters')
        .max(15, 'Username must be at most 15 characters'),
      email: Yup.string().email('Invalid email address').required('Email is required'),
      password: Yup.string().required('Password is required'),
    }),
    // onSubmit is called when the form is submitted
    onSubmit: (values) => {
      // Handle form submission logic here (e.g., send data to server)
      console.log(values);
    },
  });

  return (
    <form onSubmit={formik.handleSubmit}>
      <div>
        <label htmlFor="username">Username:</label>
        <input
          type="text"
          id="username"
          name="username"
          placeholder="Enter your username"
          // Connect input to formik state and handlers
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
          value={formik.values.username}
        />
        {/* Show error message if touched and there is an error */}
        {formik.touched.username && formik.errors.username && (
          <div style={{ color: 'red', marginTop: '5px' }}>{formik.errors.username}</div>
        )}
      </div>

      <div>
        <label htmlFor="email">Email:</label>
        <input
          type="email"
          id="email"
          name="email"
          placeholder="Enter your email"
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
          value={formik.values.email}
        />
        {formik.touched.email && formik.errors.email && (
          <div style={{ color: 'red', marginTop: '5px' }}>{formik.errors.email}</div>
        )}
      </div>

      <div>
        <label htmlFor="password">Password:</label>
        <input
          type="password"
          id="password"
          name="password"
          placeholder="Enter your password"
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
          value={formik.values.password}
        />
        {formik.touched.password && formik.errors.password && (
          <div style={{ color: 'red', marginTop: '5px' }}>{formik.errors.password}</div>
        )}
      </div>

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

export default MyForm;

Code Output:

validation using hook method

Best Practices and Tips

  1. Read the Documentation: Familiarize yourself with Formik’s documentation to understand its features and capabilities.

  2. Separate Component: Break down your form into smaller, reusable components. This makes your code modular and easier to maintain.

  3. Yup for Validation: It is advisable to integrate Yup for validation schemas with Formik. Yup provides a clean way to define and handle form validation.

Final Thoughts on Building Forms in React with Formik

Formik simplifies form management by providing a set of components and utilities, thereby reducing boilerplate code and making your codebase more concise. While Formik comes with a set of default behaviors, it is flexible enough to accommodate various form patterns and can be extended or customized based on specific project needs.

PureCode.ai can cater for your code development process. It will save you valuable time and effort on a project by providing customized, and ready-to-use components which will allow you to prioritize more important and thought-intensive tasks to speed up the development of your user interface.

Shadrach Abba

Shadrach Abba