As a software engineer at FSL, I am constantly tasked with finding up-to-date solutions to classic development problems. One such problem is effective and efficient form management.
I’ve spent much of my professional career over the last few years building web applications with React, which has a growing list of libraries developed specifically to make managing forms easier.
Form libraries simplify the tedious task of managing user input by:
- Gathering user input or displaying a stored value
- Managing form state to figure out if a form has been altered or a field has been touched
- Assisting with input validation
If you are building a web application with a large number of forms, or an app that requires advanced forms that have dynamic field arrays, conditionals or any type of dependent form field, form libraries can help speed up the development process.
Below you’ll find some thoughts on my experiences with a handful of the most popular libraries -
Redux Form, React Final Form, Formik, and Yup.
This article won’t cover performance testing, or conclude that one library is better than another. Instead, it will offer my take on some of the benefits and drawbacks of each.
Note: In order to take full advantage of these libraries and effectively manage your forms, it’s necessary to write form field wrappers. In the past I’ve used Material UI, Baseweb or Bootstrap to write wrapper components for all field types (select, radio, checkbox, text input, text area).
The documentation provides a good list of examples that include codebox editable models.
- Easy to learn
- State selectors make it easy to subscribe to changes in form fields, which can make it easier to implement conditional or dependent form fields.
- Pretty much tied to redux. You have to be using redux within your project to utilize redux form.
- It also struck me as odd that there was no simple way to find a list of fields that had been touched/edited.
React Final Form
The documentation is pretty thorough and does a decent job of highlighting very common usage scenario examples, such as sync/async record validation, autosave, conditional fields, and typeahead field support.
- Easy to learn
- Appears to have some preliminary support for hooks.
- Supports components rendering and render prop rendering.
- Library uses the observer pattern for subscription-based changes so it can help tune/cut down form re-renderings on change (for performance gains).
- The last time I used this library, I ran into a lot of weird quirks with arrays of form items. I think in today's form development landscape, dynamic arrays of form fields should be considered first-class citizens, and support should be robust. The out-of-the-box implementation doesn’t really ship with code to handle form arrays. Array handling is offered as a plugin, but it seems strange that something this common was not included in the core library.
The documentation is very well organized. It has inline examples and includes samples of parts of the functionality. It doesn’t really have a base of examples for common scenarios, but the overall format is clean and easy enough to follow.
- Integrates out-of-the-box with a great library called Yup for object schema validation.
- This allows you to define the data structure for your form, and ensures that all the values of the form validate to comply with the rules you have defined. It does a good job of separating the form design from the data validation rules.
- Allows reference to a field by its deeply nested path. I was a big fan of the ability to reference nested objects and/or array fields by name or number. I found a lot of cases where this feature was useful.
- Learning curve was somewhat steep. Once you wrap form components as necessary, though, form writing is a breeze.
- Formik is very opinionated when it comes to validating fields out of the box. It does use Yup, a library of which I am generally a fan, but when paired with Formik the integration only allows validation of the entire form at once. The integration does not allow for individual field validation against a Yup schema. Formik has a validateField function that requires a custom validation function, but it has nothing to do with the Yup integration, which is counterintuitive.
- While working on a client project, my team had to write custom onBlur handlers to validate a single field onBlur from the Yup schema. We also needed to turn on field validation onChange, so that we could switch a field from an error state back to its normal state. This required some hands-on custom state handling, and it took a bit of work to juggle the source of truth for field state.
- Field validation is baked in, by default, onBlur and onChange. This validation trigger caused a ton of re-rendering, quickly making typing responsiveness and performance sluggish on even a medium (15 fields or more) form. We were forced to disable out of the box onBlur and onChange validation.
- At the moment, Formik is primarily steered by one developer. This is a downside, as it can lead the library to be overly-opinionated (the cause of a few of the issues listed above).
At FullStack Labs, we are consistently asked for ways to speed up time-to-market and improve project maintainability. We pride ourselves on our ability to push the capabilities of these cutting-edge libraries. Interested in learning more about speeding up development time on your next form project, or improving an existing codebase with forms? Contact us.