Yup, you should use React Hook Form

React and Forms, we’ve all been there

Explorations

I ended up writing my own framework when it was crunch time, and the longer I worked with it, the more I realized it only worked because it fit how I thought about forms in React. It aligned with my views on AngularJS (formatter & parser pipelines).

Formik — https://jaredpalmer.com/formik/

I had used Formik in the past, to somewhat meager success. It was great for true forms but struggled on multi-step forms. They have since added “wizard” forms, but it doesn’t feel very intuitive.

Redux Form — https://github.com/redux-form/redux-form

We’re redux, we’re react, it seemed like a decent option. Nope! Definitely not. Even in their readme they allude to it being entirely inappropriate as a solution. He and I are in agreement: you should not tie your rendering to your choice in data store.

React Hook Form

React hook form was my final exploration and ended up being my choice. From here on out, we’ll talk about RHF and why I believe it’s a great solution.

RHF Strengths

  1. Pretty seamless implementation. I find it to be extremely clean with a single hook call abstracting away a ton of underlying set up.
  2. Configurable — The hook functionality is flexible for many different situations.
  3. Built in validation — RHF includes local validation, as well as the ability to pass in a validation schema (more on this later).
  4. We don’t need to use Yup for validation. You can choose to provide your own validation schema, or use Yup, their suggested library. Which, by the way, has over a million weekly downloads (React has 6 million).
  5. Ability to change output shape within the form itself.
  6. Performance! React hook form, utilizing hooks, demolishes the competition of Formik and Redux forms.
  7. PropTypes becomes much easier for defining your form components because you’re not accessing the props directly (RHF manages it for you)

RHF Downsides

  1. Must be used within a functional component (hook requirement).
  2. Hooks. They’re relatively new to React, but do make for clean code (in my opinion).
  3. Updating the redux store isn’t super seamless. You have to perform an “updateFields” callback on blur of the input
  4. Formatting the input string (i.e. adding commas into a number) needs to call setValue again (this is more of a “neutral” point because we already do this within our current form framework)
  5. Nested inputs with their own validation can be a bit hard. For instance, if you have two inputs that are tied together (for instance, a % of a whole), the schema and internal values need to be managed together and also pass validation, but the parent only cares about the value & an whether or not it’s an error

Yup

In case you have not had exposure to Yup, it is a declarative validation schema that provides chainable functions with pretty staggering capabilities.

Yup Strengths

  1. Insanely readable.
  2. Prioritization of validation as a result of the chaining (i.e. number().required().positive()) will error if there is data that isn’t a number, error if undefined yet required, and if it’s a valid number that’s not positive, will error.
  3. Custom error messages per validation failure. These error messages are pretty slick, you can interpolate the value that failed, the values entered into the validation function (i.e. min(0), 0 can be interpolated).
  4. Casting! Using the same exact validations, you can cast an input into a usable output (i.e. converting strings to numbers)
  5. Dynamic logic chains — You can use when to interpolate values from other properties to change the schema. For instance, using if you entered a value and want to use that to be the maximum of another property, you can!
  6. Concatenation of schemas: concat. This allows for complex forms & wizards to be validated across different areas of the app, and then have a final verification as a whole concept.

Yup downsides

  1. It’s an external dependency — They have different opinions, approaches, changes we’re not privy to. For instance `number` reports `1,234` as invalid because of the comma. The only way around this was to create a new validation type. I would have personally done a logical sanitation before passing it to parseFloat
  2. Hard to swap out of once Yup has been adopted at a full application level. That’s a lot of validation to rewrite.

Bundle size impact

Images gathered through https://bundlephobia.com/

React hook form adoption

React hook form has 8% of Formik and only 13% of Redux-Form weekly downloads. While this is a pretty glaring problem, hooks are new and broad adoption of a new hook based approach to forms will likely be an uphill battle. I do, however, think that the trade offs are well worth it.

How I see us using this

The high level approach:

  1. Schemas live in a separate package (we utilize Lerna, so this equates to an npm module)
  2. Schemas are imported into the forms, and used in the `useForm` hook
  3. Updates to the store are performed on each change, updating the store with values/errors
  4. Using concat, we can perform complex validation across the entire “wizard forms”

Schemas living in a separate package

Yup schemas fulfill several roles as it pertains to the application data. Not only is it performing validation for the form itself (in the React hook form hook configuration), but also to cast data into a usable form in the reducer to then perform manipulation/calculations upon. This can be done by utilizing Yup’s cast call on a schema for a given data object.

Updates to the store are performed when hooks callbacks are fired

Most forms should be performing updates onBlur instead of onChange, but either way the callback should consist of 3 steps:

Complex, multi-step, validation

Given the ability to do concat with schemas, and also branching validation, we can utilize this to do validation before even hitting the API.

Conclusion

Both libraries, Yup and react-hook-form are pretty solid implementations of each problem they are trying to solve. If anything can be taken away from the above is that either are able to stand on their own with flying colors. Combined, they make for a spectacular development experience.

--

--

Front End Developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store