Categories
React

How I Build Forms Quickly in React

RJSF is a declarative form builder for React. In this post I’ll show you why it’s my favorite React form library.

Forms are everywhere in web apps. Whenever you log in, make a post on social media, or buy something online, you're using a form.

Despite their ubiquity, building forms requires a lot of attention and care. Form fields should only accept specific types of data, perform validations, and show errors on invalid input. As more fields are added, the complexity of the form grows.

This work is repetitive and tiring. Wouldn't it be great if we could make form building trivial?

Enter RJSF

I've tried lots of form libraries, but none solve the burden of easy, rapid form building as well as RJSF does.

What makes forms difficult is the management of JSX, state, validations, and errors. As you add more fields, you also need to manage more of the aforementioned things, which can get overwhelming fast.

RJSF solves this by being a declarative form builder. Instead of manually defining the form and validation logic, you describe your form using json-schema, and RJSF handles the rest.

I've been using it in production with my clients to great effect. To show you how it works, we'll make a quick sign up form. Familiarity with json-schema is helpful, so here is a 5 minute primer.

Making a Sign Up Form

We first need to collect the user's email and password. This is what the RJSF react code looks like:

<Form
  schema={{
    title: "Signup",
    properties: {
      email: {
        type: "string"
      },
      password: {
        type: "string"
      }
    }
 }}
/>

From this small bit of code, RJSF has built a heading, text inputs, and submit button. Cool, but this is far from done. Some improvements we can make:

  • Make email and password required fields
  • Enforce minimum password length
  • email field should only accept emails
  • password input should be obfuscated

Let's add these in.

Make email and password required fields:

<Form
  schema={{
    title: "Signup",
    properties: {
      email: {
        type: "string"
         },
      password: {
        type: "string"
      },
    },
    required: ["email", "password"]
  }}
/>

Enforce minimum password length

<Form
  schema={{
  title: "Signup",
  properties: {
    email: {
      type: "string"
    },
    password: {
      type: "string",
      minLength: 8
    },
  },
  required: ["email", "password"]
}}
/>

email field should only accept emails

<Form
  schema={{
    title: "Signup",
    properties: {
      email: {
        type: "string"
      },
      password: {
        type: "string",
        minLength: 8
      },
    },
    required: ["email", "password"]
  }}
  uiSchema={{
    "email": {
      "ui:widget": "email"
    }
  }}
/>

password input should be obfuscated

<Form
  schema={{
    title: "Signup",
    properties: {
      email: {
        type: "string"
      },
      password: {
        type: "string",
        minLength: 8
      },
    },
    required: ["email", "password"]
  }}
  uiSchema={{
    "email": {
      "ui:widget": "email"
    },
    "password": {
      "ui:widget": "password"
    }
  }}
/>

And here is the final result (View the code here.)

RJSF supports HTML native error handling, as well as custom JS error handling.

What Else Can RJSF Do?

This is just scratching the surface. RJSF has much more to offer.

Themes

Native support for popular libraries like chakra, semantic-ui, material design, and more.

Complex Fields

Multi-select dropdowns, check boxes, configurable lists, and much more are supported out of the box. If you need, you can also create your own custom form fields.

Custom Validations & Errors

Add custom validations to your form. Here is a custom "password match" validation:

<Form 
  validate={(formData, errors) => {
    if (formData.pass1 !== formData.pass2) {
      errors.pass2.addError("Passwords don't match");
    }
    return errors;
  }}
  schema={{
    type: "object",
    properties: {
      pass1: {type: "string", minLength: 3},
      pass2: {type: "string", minLength: 3},
    }
  }}
/>

What are the RJSF Cons?

While RJSF is great, it also comes with downsides:

  • Large Forms are Slow
    I noticed this firsthand when building a dropdown with over 50 options. My form was super slow because of this. Reducing the options to ~15 seemed to solve it.

RJSF is fantastic if you're still figuring out the data your form is collecting. However, the docs mention that "if you have a priori knowledge of your data and want a toolkit for generating forms for it, you might want to look elsewhere".

Conclusion

This was a quick dive into RJSF, my favorite react library for rapid form development.

If you'd like to try it out, check out this playground. It has tons of examples that show the power of RJSF. If you dig it, help the maintainers out by giving them a star on GitHub ⭐️

Want more web dev tips? Follow me on twitter and subscribe to my newsletter.

Processing…
Success! You're on the list.

Leave a Reply

Your email address will not be published. Required fields are marked *