Top React Form Libraries for Efficient Form Creation

Introduction

As front-end developers, forms play a crucial role in our daily work. Rather than reinventing the wheel and writing forms from scratch every time, it's important to understand the various libraries available to streamline and simplify the form-building process.

In this article, we will explore top React form libraries that can help us create efficient and user-friendly forms with ease.

1. SurveyJS React Form Library

SurveyJS React Form Library is a tool for React applications that helps create dynamic forms on the client side. It uses JSON objects to define the structure and behaviour of forms.

It's one of the popular open-source form libraries, with 3.9k stars on GitHub and 17.4k user downloads on npm.

SurveyJS

Features:

  • Dynamic forms for JavaScript application

  • 20+ built-in question types and support for custom question types

  • Built-in themes and CSS customization

  • Answer validation

  • TypeScript support

  • Integration with any backend framework (examples for PHP, - NodeJS, and ASP.NET included)

  • Compatibility with any server + database combination Third-party component integration

How to use

Here are the steps to add a React Survey form to a React application:

This will result in a form similar to this one:



import { useCallback } from "react";

import "survey-core/defaultV2.min.css";
import { Model } from "survey-core";
import { Survey } from "survey-react-ui";

const surveyJson = {
  elements: [
    {
      name: "FirstName",
      title: "Enter your first name:",
      type: "text",
    },
    {
      name: "LastName",
      title: "Enter your last name:",
      type: "text",
    },
  ],
};

function App() {
  const survey = new Model(surveyJson);
  survey.focusFirstQuestionAutomatic = false;

  const alertResults = useCallback((sender) => {
    const results = JSON.stringify(sender.data);
    alert(results);
  }, []);

  survey.onComplete.add(alertResults);

  return <Survey model={survey} />;
}

export default App;

2. React Hook Form

React Hook Form

React Hook Form - Performant, flexible and extensible forms with easy-to-use validation. It's one of the most popular form libraries, with 33.5k stars on GitHub and 3.1 million user downloads on npm.

Features:

  • Performance: Minimizes the number of re-renders, reduces validation computation, and faster mounting.

  • Super Light: Package size matters. React Hook Form is a tiny library without any dependencies.

  • HTML standard: Embraces native HTML form validation

  • Adoptable: it can be easily adopted without other dependencies.

  • Support Yup, Zod, AJV, Superstruct, Joi and others

How to Install:

npm i react-hook-form

How to use:

    import { useForm } from 'react-hook-form';
    function App() {
      const {
        register,
        handleSubmit,
        formState: { errors },
      } = useForm();

      return (
        <form onSubmit={handleSubmit((data) => console.log(data))}>
          <input {...register('firstName')} />
          <input {...register('lastName', { required: true })} />
          {errors.lastName && <p>Last name is required.</p>}
          <input {...register('age', { pattern: /\d+/ })} />
          {errors.age && <p>Please enter number for age.</p>}
          <input type="submit" />
        </form>
      );
    }

The code above is an example usage of the useForm hook from the react-hook-form library in a React component.

The useForm hook is used to manage form state and validation.

In the example, the register function is used to register the input fields in the form, and returns the necessary props for each input. The handleSubmit function is passed to the onSubmit prop of the form and it is responsible for handling the form submission.

The formState object returned by useForm includes the current state of the form, including any errors that have been detected during validation.

The example defines a form with three input fields; first name, last name, and age. The last name input is required, and the age input requires a numeric value.
If the user leaves the last name field empty or enters a non-numeric value for the age field, an error message is displayed.

When the form is submitted, the handleSubmit function logs the form data to the console.

3. Formik

Formik

Formik allows us to build complex forms easily. It's also one of the most popular open-source form libraries for React and React Native. It has 32k stars on GitHub and 2.4 million user downloads on npm.

Features:

  • Declarative: Formik handles the repetitive and annoying stuff—keeping track of values/errors/visited fields, orchestrating validation, and handling submission.

  • Intuitive: Formik makes debugging, testing, and reasoning about our forms a breeze by staying within the core React framework and away from magic.

  • Adoptable: Formik does not use external state management libraries like Redux or MobX.

How to Install:

    npm i formik

How to use:

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

    const Basic = () => (
      <div>
        <h1>Any place in your app!</h1>
        <Formik
          initialValues={{ email: '', password: '' }}
          validate={values => {
            const errors = {};
            if (!values.email) {
              errors.email = 'Required';
            } else if (
              !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
            ) {
              errors.email = 'Invalid email address';
            }
            return errors;
          }}
          onSubmit={(values, { setSubmitting }) => {
            setTimeout(() => {
              alert(JSON.stringify(values, null, 2));
              setSubmitting(false);
            }, 400);
          }}
        >
          {({ isSubmitting }) => (
            <Form>
              <Field type="email" name="email" />
              <ErrorMessage name="email" component="div" />
              <Field type="password" name="password" />
              <ErrorMessage name="password" component="div" />
              <button type="submit" disabled={isSubmitting}>
                Submit
              </button>
            </Form>
          )}
        </Formik>
      </div>
    );

    export default Basic;

The usage example above defines a component that renders a form with an email and password input, and a submit button.
The Formik component wraps the form and provides functionality for handling form state, validation, and submission.

The initialValues prop defines the initial values for the form inputs, and the validate function is used for form validation. If any errors are detected, they are returned as an object.

The onSubmit function is called when the form is submitted, and it can be used to perform any necessary actions, such as sending data to a server or updating the application state.

The Formik component takes a render prop that is used to define the form fields and error messages. The Field component is used to define the form input fields, and the ErrorMessage component is used to display any validation errors.

Finally, the submit button is disabled when the form is submitting to prevent multiple submissions.
This is just one example of how Formik can be used in a React application to manage forms with complex validation and submission logic.

React Hook Forms Vs Formik

React Hook FormFormik
ComponentUncontrolled & ControlledControlled
APIHooksComponents + Hooks
Package sizeSmall

react-hook-form@7.27.0
**8.5KB** | Medium
formik@2.1.4
**15KB** | | Validation | Built-in, Yup, Zod, Joi, Superstruct and allow custom validation. | Custom or Yup | | Learning curve | Low to Medium | Medium |

4. rc-field-form

rc-field-form

rc-field-form- React Performance First Form Component. It has 783 stars on GitHub and 885k user downloads on npm.

Features:

  • Support react.js and even react-native

  • Validate fields with async-validator

How to Install:

 npm i rc-field-form

How to Use:


    import Form, { Field } from 'rc-field-form';

    const Input = ({ value = "", ...props }) => <input value={value} {...props} />;

    const Demo = () => {
      return (
        <Form
          onFinish={(values) => {
            console.log("Finish:", values);
          }}
        >
          <Field name="username">
            <Input placeholder="Username" />
          </Field>
          <Field name="password">
            <Input placeholder="Password" />
          </Field>

          <button>Submit</button>
        </Form>
      );
    };

    export default Demo;

The usage example above defines a component called Demo that renders a form with two input fields for a username and password.

The Form component wraps the form and provides functionality for handling form state, validation, and submission. The onFinish prop is called when the form is submitted and receives an object with the form values.

The Field component is used to define the form fields and provide validation rules. The name prop is used to define the name of the field, and any custom validation rules can be defined using the rules prop.

The Input component is a custom input field that receives the value prop and any additional props. It is used to define the input fields for the form.
Finally, the submit button is defined outside of the Field components and is used to trigger the form submission.

This is just one example of how rc-field-form can be used in a React application to manage form fields and handle the form submission.

5. React Final Form

React Final Form

React Final Form - High-performance subscription-based form state management for React. It follows the observer design pattern in which components subscribe to events as they occur. It does not re-render the entire form, only the fields that have subscribed to re-render. It has 7.2k stars on GitHub and 364k user downloads on npm.

Features:

  • Zero dependencies (that affect the bundle size)

  • Only peer dependencies: React and React Final Form

  • Opt-in subscriptions - only update on the state we need!

How to Install:

    npm i react-final-form

How to Use:


    import { Form, Field } from 'react-final-form'

    const MyForm = () => (
      <Form
        onSubmit={onSubmit}
        validate={validate}
        render={({ handleSubmit }) => (
          <form onSubmit={handleSubmit}>
            <h2>Simple Default Input</h2>
            <div>
              <label>First Name</label>
              <Field name="firstName" component="input" placeholder="First Name" />
            </div>

            <h2>An Arbitrary Reusable Input Component</h2>
            <div>
              <label>Interests</label>
              <Field name="interests" component={InterestPicker} />
            </div>

            <h2>Render Function</h2>
            <Field
              name="bio"
              render={({ input, meta }) => (
                <div>
                  <label>Bio</label>
                  <textarea {...input} />
                  {meta.touched && meta.error && <span>{meta.error}</span>}
                </div>
              )}
            />

            <h2>Render Function as Children</h2>
            <Field name="phone">
              {({ input, meta }) => (
                <div>
                  <label>Phone</label>
                  <input type="text" {...input} placeholder="Phone" />
                  {meta.touched && meta.error && <span>{meta.error}</span>}
                </div>
              )}
            </Field>

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

The code above is an example of using React Final Form library to create a form with various types of fields such as text input, reusable custom component, and render functions. The form component takes in an onSubmit function and a validate function to handle form submission and validation respectively. The Field component is used to create each field, and it can accept a component prop to render the field with a custom component or a render prop to render the field with a custom function. The input value and state are managed by the library, and any validation errors are displayed when the user interacts with the form.

rc-field-form Vs React Final Form

rc-field-formReact Final Form
ComponentA component library for building forms in React.A library for building forms in React.
APIIt provides Form, FormItem, and other form components that can be used to build a form.It provides a <Form> component and a <Field> component that can be used to build a form.
Package sizeThe package size of RC-Field-Form is around 105 KB.The package size of React Final Form is around 38 KB.
ValidationIt provides built-in validation rules, such as required, pattern, and maxLength. It also allows custom validation rules.It provides validation through a validation function, which can be passed as a prop to the <Field> component. It also allows custom validation functions.
Learning curveIt provides good documentation and examples to get started.It also has good documentation and examples to get started.

6. react-credit-cards

react-credit-cards

react-credit-cards- A sleek credit card component for React. It has 2.4k stars on GitHub and 27.9k user downloads on npm.

Features:

  • react-credit-cards support all credit card issuers available in Payment plus Hipercard (a Brazilian credit card).

How to Install:

npm i react-credit-cards

How to Use:


    import React from 'react';
    import Cards from 'react-credit-cards';

    export default class PaymentForm extends React.Component {
      state = {
        cvc: '',
        expiry: '',
        focus: '',
        name: '',
        number: '',
      };

      handleInputFocus = (e) => {
        this.setState({ focus: e.target.name });
      }

      handleInputChange = (e) => {
        const { name, value } = e.target;

        this.setState({ [name]: value });
      }

      render() {
        return (
          <div id="PaymentForm">
            <Cards
              cvc={this.state.cvc}
              expiry={this.state.expiry}
              focused={this.state.focus}
              name={this.state.name}
              number={this.state.number}
            />
            <form>
                <input
                type="tel"
                name="number"
                placeholder="Card Number"
                onChange={this.handleInputChange}
                onFocus={this.handleInputFocus}
              />
              ...
            </form>
          </div>
        );
      }
    }

The code above is an example of a simple credit card payment form in React, using the react-credit-cards library to display the credit card as it's being filled out. The form includes inputs for the card number, expiration date, cardholder name, and CVC code. The state of the form is managed in the component's state object, with handleInputFocus and handleInputChange methods to update the state and keep track of the currently focused input field. When the form is submitted, the data can be sent to a backend for processing.

7. formsy-react

formsy-react

formsy-react- A form input builder and validator for React. It has 761 stars on GitHub and 25k user downloads on npm.

Features:

  • Build any form element components. Not just traditional inputs, but anything we want, and get that validation for free

  • Add validation rules and use them with simple syntax

  • Use handlers for different states of our form. (onSubmit, onValid, etc.)

  • Pass external errors to the form to invalidate elements (E.g. a response from a server)

  • Dynamically add form elements to our form, and they will register/unregister to the form

How to Install:

 npm i formsy-react

How to Use:


    // MyInput.js
    import { withFormsy } from 'formsy-react';
    import React from 'react';

    class MyInput extends React.Component {
      constructor(props) {
        super(props);
        this.changeValue = this.changeValue.bind(this);
      }

      changeValue(event) {
        // setValue() will set the value of the component, which in
        // turn will validate it and the rest of the form
        // Important: Don't skip this step. This pattern is required
        // for Formsy to work.
        this.props.setValue(event.currentTarget.value);
      }

      render() {
        // An error message is passed only if the component is invalid
        const errorMessage = this.props.errorMessage;

        return (
          <div>
            <input onChange={this.changeValue} type="text" value={this.props.value || ''} />
            <span>{errorMessage}</span>
          </div>
        );
      }
    }

    export default withFormsy(MyInput);

The code above defines a custom input component MyInput using formsy-react library. The withFormsy higher-order component is used to wrap the input component to enable it to work with formsy-react.
The component defines a changeValue method that sets the value of the input component and triggers the form validation. The render method returns the input element along with an error message, which is displayed only when the component is invalid.
This code can be used to create custom input components with validation capabilities using formsy-react.

react-credit-cards Vs formsy-react

react-credit-cardsformsy-react
ComponentA component library for displaying credit card input fields and validating credit card information.A library for building forms in React.
APIIt provides a single **<Cards>** component that can be used to display credit card input fields. It also provides props for customization.It provides a <Form> component and a <Field> component that can be used to build a form.
Package sizeThe package size of React Credit Cards is around 14 KB.The package size of Formsy React is around 25 KB.
ValidationIt provides built-in validation rules for credit card number, expiration date, and security code. It also allows custom validation rules.It provides validation through a validation function, which can be passed as a prop to the <Field> component. It also allows custom validation functions.
Learning curvegood documentation and examples to get started.It also has good documentation and examples to get started.

8. react-form

react-form

react-form- Hooks for managing form state and validation in React. It has 2.5k stars on GitHub and 14.3k user downloads on npm.

Features:

  • Built with React hooks for React hooks

  • Highly practical validation API with 1st-class asynchronous support

  • Built-in validation debouncing with auto cancellation for stale validations

  • Field Scoping for deeply nested form values

  • No-nonsense meta-management for both forms and form fields

  • Fully memorized for frequent and fast rerenders

  • Flexible form API at the field, scope, and form levels

How to Install:


    npm i react-form

How to Use:



    import React from "react";
    import ReactDOM from "react-dom";

    import { useForm, useField } from "react-form";

    async function sendToFakeServer(values) {
      await new Promise(resolve => setTimeout(resolve, 1000));
      return values;
    }

    function validateAddressStreet(value) {
      if (!value) {
        return "A street is required";
      }
      return false;
    }

    async function validateName(name, instance) {
      if (!name) {
        return "A name is required";
      }

      return instance.debounce(async () => {
        console.log("checking name");
        await new Promise(resolve => setTimeout(resolve, 1000));
        // All names are valid, so return a false error
        return false;
      }, 500);
    }

    function NameField() {
      const {
        meta: { error, isTouched, isValidating },
        getInputProps
      } = useField("name", {
        validate: validateName
      });

      return (
        <>
          <input {...getInputProps()} />{" "}
          {isValidating ? (
            <em>Validating...</em>
          ) : isTouched && error ? (
            <em>{error}</em>
          ) : null}
        </>
      );
    }

    function AddressStreetField() {
      const {
        meta: { error, isTouched, isValidating },
        getInputProps
      } = useField("address.street", {
        validate: validateAddressStreet
      });

      return (
        <>
          <input {...getInputProps()} />{" "}
          {isValidating ? (
            <em>Validating...</em>
          ) : isTouched && error ? (
            <em>{error}</em>
          ) : null}
        </>
      );
    }

    function MyForm() {
      // Use the useForm hook to create a form instance
      const {
        Form,
        meta: { isSubmitting, canSubmit }
      } = useForm({
        onSubmit: async (values, instance) => {
          // onSubmit (and everything else in React Form)
          // has async support out-of-the-box
          await sendToFakeServer(values);
          console.log("Huzzah!");
        },
        debugForm: true
      });

      return (
        <Form>
          <div>
            <label>
              Name: <NameField />
            </label>
          </div>
          <div>
            <label>
              Address Street: <AddressStreetField />
            </label>
          </div>

          <div>
            <button type="submit" disabled={!canSubmit}>
              Submit
            </button>
          </div>

          <div>
            <em>{isSubmitting ? "Submitting..." : null}</em>
          </div>
        </Form>
      );
    }

    function App() {
      return <MyForm />;
    }

    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);

The usage example above is a React code that uses the react-form library to handle form validation and submission. It creates a form instance using the useForm hook and defines two form fields (NameField and AddressStreetField) using the useField hook, each with its own validation function.

The MyForm component renders the form and handles submission. When the form is submitted, it sends the form data to a fake server using sendToFakeServer function. It also displays an error message if the form data is invalid, and displays a "Submitting..." message while the form is being submitted. Finally, the **App** component renders the MyForm component.

9. uniforms

uniforms

uniforms- A React library for building forms from any schema. It has 1.7k stars on GitHub and 13.9k user downloads on npm.

Features:

  • Automatic forms generation

  • Fields capable of rendering every schema

  • Helper with creating custom fields with one line

  • Inline and asynchronous form validation

  • Integrations with various schemas

  • Wide range of themes:

How to Install:


    npm i uniforms

How to Use:


    import React from 'react';
    import { AutoForm } from 'uniforms-semantic';

    import { bridge as schema } from './GuestSchema';

    export function GuestFormBasic() {
      return <AutoForm schema={schema} onSubmit={console.log} />;
    }

The code above creates a basic form using the **uniforms-semantic** library with a predefined schema and a console log statement to display the form data when it is submitted.

react-form Vs uniforms

react-formuniforms
ComponentBuilt with React hooks for React hooksA library for building forms in React.
APIFlexible form API at the field, scope, and form levelsIt provides a set of components that can be used to build a form, including <AutoForm>, <LongTextField>, <SelectField>, and more.
Package sizeThe package size of React Form is around 14 KB.The package size of Uniforms is around 72 KB.
ValidationBuilt-in validation debouncing with auto cancellation for stale validationsIt provides a simple schema-based validation system, which can be used to validate form inputs. It also allows custom validation functions.
Learning curvegood documentation and examples to get started.good documentation and examples to get started.

10. MobX React Form

MobX React Form

MobX React Form- Reactive MobX Form State Management. It has 1.1k stars on GitHub and 7.2k user downloads on npm.

Features:

  • Extensible Validation Plugins.

  • Sync & Async Validation (w/ Promises & automatic errors).

  • Nested Fields (w/ Serialization & Validation).

  • Nested Forms (w/ Nested Submission & Validation Hooks).

  • Event Hooks, Event Handlers & Validation Hooks

  • Observers & Interceptors

  • Bindings for custom Components.

  • Support for Material UI, React Widgets, React Select & more.

  • Dedicated DevTools Package.

How to Install:

    npm i mobx-react-form

How to Use:


    import React from 'react';
    import { observer } from 'mobx-react';

    export default observer(({ myForm }) => (
      <form onSubmit={myForm.onSubmit}>
        <label htmlFor={myForm.$('email').id}>
          {myForm.$('email').label}
        </label>
        <input {...myForm.$('email').bind()} />
        <p>{myForm.$('email').error}</p>

        {/* ... other inputs ... */}

        <button type="submit" onClick={myForm.onSubmit}>Submit</button>
        <button type="button" onClick={myForm.onClear}>Clear</button>
        <button type="button" onClick={myForm.onReset}>Reset</button>

        <p>{myForm.error}</p>
      </form>
    ));

The code above creates a form component using React and the mobx-react library. The observer function is used to make the component reactive to changes in the form state managed by MobX.

The form component renders a form element with input fields generated based on the myForm object passed as a prop. The myForm object is expected to have methods and properties provided by MobX to handle form validation, submission, clearing, and resetting.

The input fields are generated using the bind method of the $ object which generates the necessary properties and handlers for the input field to be reactive to changes.

The form also includes buttons for submission, clearing, and resetting the form. The myForm.onSubmit, myForm.onClear, and myForm.onReset methods are called respectively when the buttons are clicked.

11. HouseForm

HouseForm

HouseForm - Field-First React Form Validation, where our form validation and UI code live harmoniously. It has 173 stars on GitHub and 191 user downloads on npm.

Features:

  • Field First: Consolidate our UI and validation logic in one location - our fields.

  • Headless & runtime agnostic: Use HouseForm in any React-supported environment, from native apps to the CLI.

  • Zod Powered: Easily set up complex validations for our form fields.

  • Flexible API: Mix and match which validation methods work best per field.

  • Lightweight: HouseForm has a smaller bundle of less than 4KB GZIP.

  • Fast: Our benchmarks have us on par or faster than common alternatives.

How to Install:


    npm i houseform

How to Use:


    import {Form} from 'houseform';

    const App = () => (
        <Form onSubmit={() => {}}>
            {({submit}) => <button onClick={submit}>Submit</button>}
        </Form>
    )

The App component renders the Form component with an onSubmit prop set to an empty arrow function.
The Form component accepts a function as a child with a submit argument provided. This function returns a button element with an onClick event handler set to the submit function.
When the button is clicked, it triggers the submit function provided by the Form component to handle the form submission logic.

HouseForm Vs MobX React Form

HouseFormMobX React Form
ComponentHouseForm uses uncontrolled componentsUncontrolled & Controlled
APIFlexible APIIt provides a set of components that can be used to build a form, including <Form>, <Field>, and <Errors>
Package sizeHouseForm is 13.5kb unminified without GZIP110.6 kB Minified and 28.7kb Minified + GZIPPED
ValidationHouseForm uses Zod for validationExtensibles Validation Plugins.
Learning curvegood documentation and examples to get started.good documentation and examples to get started.

Conclusion

Thanks for checking out this piece! Hope it was helpful for your coding journey. Keep on coding, and have fun!