At last, React forms management became a no-brainer

ยท 3 mins read

Let's face it, building forms in React apps used to be a huge pain for some years.

Hopefully now we can use libraries likes Formik with some Yup flavour so the Development Experience is way better than it used to be.

If you have met React after the Hooks launch probably you don't have a clue what I am talking about, but I am sure there are people having spent tons of hours trying to figure out how to make form fields update under circumstances while feeling totally overwhelmed.

# The Redux Form era

A couple years ago, the goto option was Redux Form so this library was the main tool me and the web development teams I was responsible for were using.

Because of it, applications were full of boilerplate code and the same validation rules were repeated again and again here and there.

Engineers were trying hard to keep things as clean as possible by creating reusable and abstracted pieces of logic but this wasn't always an easy task and definitely demanded some extra effort from their side. In fact, there were various forms with manual state management here and there to prevent us from bringing Redux Form into the game for the shake of small forms with 2-3 fields.

As you get, the Development Experience was awful so developers were trying to use it as little as possible!!

I remember myself preaching how easy it was to build and manage forms with other solutions like VueJS 2.X which had started gaining some traction back then since forms management was a clear disadvantage of ReactJS.

In fact, people coming from other frameworks like Angular were also astonished after realizing all this mess and actually felt sorry for React developers.

# Why forms need some extra effort in React?

As we all know React is a library, so it doesn't offer all these bells and whistles we actually need when we are building large-scale Rich Internet Applications.

We can definitely control React forms ourselves using the controlled input pattern but this doesn't really scale as we can see below:

import React from 'react';

export default function MyComponent(props) {
  const [value, setValue] = React.useState('');

  return (
    <form onSubmit={() => console.log(value)}>
      <input
        value={value}
        onChange={e => setValue(e.target.value)}
      />
      <button>Submit</button>
    <form>
  );
}

React doesn't come with an out-of-the box solution for 2-way data binding which is ok for most things but when it comes about forms it forces us to do too many things on our own to manage fields state and accomplish even basic stuff.

Imagine now a real-life form with 10 fields or more.

This is why we need a 3rd party library to manage our forms effectively without having to add a ton of state variables for each form field we need to handle.

# The rise of 2nd generation form libraries

At some point, React Final Form and Formik were born following Redux Form footsteps copying much of its APIs while introducing some new ones. They both offer Hooks and render props APIs to help us manage our forms using the approach that serves our needs best.

This was a big stepping stone for the React community since we realized that local state has quite some power, so we don't actually need to put everything, including our forms state, to the global state management layer.

Of course, React Hooks rise helped a ton for this mindset shift in the community.

Following this rise, React Hook Form was born offering a pure Hooks-based API.

# Formik and Yup for the win

As mentioned above, I have been using Formik with Yup mostly for the last 3 years quite successfully I have to admit. The other two libraries are pretty decent options of course so all this is a matter of personal preference.

Development Experience is definitely way better so now, having even simple forms here and there without using Formik or Yup to manage them, feels silly.

Yup has helped to reduce boilerplate regarding validation rules which is another important part of the equation.

In order to see the difference, please compare the following validation rules written with vanilla JavaScript:

const errors = {};

if (!values.firstName) {
  errors.firstName = "Please enter your first name";
}

if (!values.lastName) {
  errors.lastName = "Please enter your last name";
}

if (!values.email) {
  errors.email = "Please enter your email";
}

if (values.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(values.email)) {
  errors.email = "Please enter a valid email address";
}

if (!values.message) {
  errors.message = "Please enter your message";
}

if (!values.gdpr) {
  errors.message = "Please check this to approve our GDPR policy";
}

return errors;

with this validation schema using Yup:

const ValidationSchema = Yup.object().shape({
  firstName: Yup.string().required("Please enter your first name"),
  lastName: Yup.string().required("Please enter your last name"),
  email: Yup.string()
    .required("Please enter your email")
    .email("Please enter a valid email address"),
  message: Yup.string().required("Please enter your message"),
  gdpr: Yup.boolean().oneOf(
    [true],
    "Please check this to approve our GDPR policy"
  )
});

Using vanilla JavaScript is amazing but sometimes when building large-scale applications we need to speed things up and avoid repeating ourselves.

Yup makes exactly this since it provides an easy and fast way to put together some validation logic by reducing the boilerplate.

For sure, it has a learning curve but believe me, going back to these boring if statements feels like a huge NO right now.

I have put together a dead-simple contact form using Formik, Yup, TypeScript, the beloved TailwindCSS and ReactJS of course, so you can see all these technologies in action.

Thanks for reading this. Cheers!!

Did you like this one?

I hope you really did...

Buy Me A Coffee

Newsletter

Get notified about latest posts and updates once a week!!

Support

Buy Me A Coffee