REACT FORM LIBRARY: Formik

PART II

REACT FORM LIBRARY: Formik

Formik is a form management library for React that simplifies the process of building and handling forms in your applications. It provides a set of utilities and components to manage form state, validation, and submission. Here are some key features and use cases of Formik:

Using Formik simplifies the often complex and repetitive code associated with form management, allowing developers to focus more on the application's specific features rather than dealing with the intricacies of form handling. It is widely adopted in the React ecosystem and is a powerful tool for building robust and scalable forms.

PROS:

  1. Form State Management:

    • useFormik Hook: Formik provides the useFormik hook, which returns an object containing form state, form values, form handlers (like handleChange, handleBlur, etc.), and other useful properties.
  2. Form Validation:

    • Declarative Validation: Formik integrates seamlessly with Yup, a JavaScript schema builder for validation. You can define validation rules using Yup and pass the schema to Formik's validationSchema prop.

    • Error Messages: Formik automatically handles error messages and provides a simple way to display them in your form.

  3. Form Submission:

    • onSubmit Callback: Formik allows you to define an onSubmit callback function, which is triggered when the form is submitted. This is where you can handle the submission logic, such as making API calls or updating the state.
  4. Form Components:

    • Formik Components: Formik provides components like <Field>, <Form>, <ErrorMessage>, etc., which can be used to build your forms in a declarative way. These components encapsulate common form-related tasks.
  5. Field Level Validation and Blur Handling:

    • handleBlur and handleChange: Formik's handleBlur and handleChange functions help manage the form's touched state and handle changes in form values.
  6. Dynamic Forms:

    • Dynamic Fields: Formik supports dynamic forms with varying sets of fields. You can dynamically add or remove form fields based on user interactions.
  7. Form Reset:

    • resetForm Function: Formik provides a resetForm function, which can be used to reset the form to its initial state. This is useful, for example, after a successful form submission.
  8. Integration with UI Libraries:

    • Integration with UI Libraries: Formik can be easily integrated with popular UI libraries like Material-UI, Ant Design, etc. It works well with various UI components, making it adaptable to different design systems.
  9. Formik Bag:

    • formik Bag: Formik passes a formik bag to all functions and components within its context, providing easy access to form-related properties and functions.
  10. Testing:

    • Testing Support: Formik provides utilities for testing your forms, making it easier to write unit tests for form components and form-related logic.

CONS:

  1. Large Bundle Size:

    • Formik exhibits a relatively large bundle size, potentially impacting performance in extensive applications.
  2. Complex API:

    • With a complex API offering numerous options, Formik may pose a challenge for beginners to grasp and utilize effectively.
  3. Handles Too Much State:

    • Formik manages all form state internally, potentially complicating integration with existing state management solutions.
  4. Limited Customization:

    • Customizing Formik's default behavior demands a deep understanding of its internals, with relatively few options available for customization.
  5. Depends on Yup:

    • Formik relies on Yup for form validation, introducing an additional dependency and potentially increasing bundle size.
  6. Difficult Debugging:

    • Given Formik's internal state management, debugging form state can be challenging at times.
  7. Limited Theming Support:

    • Formik lacks built-in support for form theming, necessitating customization for theming purposes.
  8. Maintenance:

    • While Formik is still considered active, it hasn't seen a significant commit in over a year. This raises concerns about its future development and potential feature updates.

    • The large codebase and bundle size further complicate maintenance efforts, making it difficult to implement changes and fix bugs efficiently.

    • This lack of active maintenance might not be a dealbreaker for small projects, but it's a crucial factor to consider for larger, more complex applications.

  9. Image Uploads:

    • Formik does not offer native support for image uploads. This means developers need to manually handle the file state using Formik's APIs, which can be cumbersome and error-prone.

    • The lack of built-in image upload functionality can be inconvenient for projects requiring file management.

    • Several alternative libraries like React-Hook-Form have built-in image upload support, making them a more suitable choice for projects with such requirements.

IMPLEMENTATION

  1. Install Formik and Yup (for validation):

    Make sure you have Formik and Yup installed in your project:

     npm install formik yup
    
  2. Create a Form Component:

    Create a new React component for your form. Here's a simple example:

     // MyForm.js
     import React from 'react';
     import { useFormik } from 'formik';
     import * as Yup from 'yup';
    
     const MyForm = () => {
       const formik = useFormik({
         initialValues: {
           name: '',
           email: '',
         },
         validationSchema: Yup.object({
           name: Yup.string().required('Name is required'),
           email: Yup.string().email('Invalid email address').required('Email is required'),
         }),
         onSubmit: (values) => {
           // Handle form submission
           console.log(values);
         },
       });
    
       return (
         <form onSubmit={formik.handleSubmit}>
           <label htmlFor="name">Name</label>
           <input
             id="name"
             name="name"
             type="text"
             onChange={formik.handleChange}
             onBlur={formik.handleBlur}
             value={formik.values.name}
           />
           {formik.touched.name && formik.errors.name ? (
             <div>{formik.errors.name}</div>
           ) : null}
    
           <label htmlFor="email">Email</label>
           <input
             id="email"
             name="email"
             type="email"
             onChange={formik.handleChange}
             onBlur={formik.handleBlur}
             value={formik.values.email}
           />
           {formik.touched.email && formik.errors.email ? (
             <div>{formik.errors.email}</div>
           ) : null}
    
           <button type="submit">Submit</button>
         </form>
       );
     };
    
     export default MyForm;
    
  3. Using the Form Component:

    Now, you can use your MyForm component in your main application file:

     // App.js
     import React from 'react';
     import MyForm from './MyForm';
    
     const App = () => {
       return (
         <div>
           <h1>Formik Example</h1>
           <MyForm />
         </div>
       );
     };
    
     export default App;
    

[OPTION 2] Form With Custom Validation

If you prefer not to use Yup for validation and want to add custom validation without it, you can directly handle validation inside the Formik onSubmit callback or use the validate prop in useFormik. Here's an example of how to add custom validation without Yup:

// MyForm.js
import React from 'react';
import { useFormik } from 'formik';

const MyForm = () => {
  const formik = useFormik({
    initialValues: {
      name: '',
      email: '',
    },
    validate: (values) => {
      const errors = {};

      // Custom validation for the "name" field
      if (!values.name) {
        errors.name = 'Name is required';
      } else if (!values.name.startsWith('A')) {
        errors.name = 'Name must start with "A"';
      }

      // Custom validation for the "email" field
      if (!values.email) {
        errors.email = 'Email is required';
      } else if (!/^\S+@\S+\.\S+$/.test(values.email)) {
        errors.email = 'Invalid email address';
      }

      return errors;
    },
    onSubmit: (values) => {
      // Handle form submission
      console.log(values);
    },
  });

  return (
    <form onSubmit={formik.handleSubmit}>
      <label htmlFor="name">Name</label>
      <input
        id="name"
        name="name"
        type="text"
        onChange={formik.handleChange}
        onBlur={formik.handleBlur}
        value={formik.values.name}
      />
      {formik.touched.name && formik.errors.name ? <div>{formik.errors.name}</div> : null}

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

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

export default MyForm;
  • While Yup provides a declarative and schema-based approach to validation, handling validation directly in the validate function offers a more imperative approach. Choose the approach that best fits your preferences and project requirements.

Make sure to import the necessary styles for your form components and handle the submission logic as needed in your actual application.

This is just a basic example, and Formik provides many more features and customization options. You can explore the official Formik documentation for more details: Formik Documentation.

OUTRO

While Formik offers a powerful solution for building forms, its limitations become apparent in larger or complex applications. To overcome these limitations, we will explore alternatives like React Hook Form and Tanstack Form.