React forms (validation) with Formik and Material-UI

Dimitris Dovinos
codefully.io
3 min readApr 5, 2019

--

The React documentation on how to deal with forms leaves a lot to the imagination. And perhaps this is fine since forms could potentially be business-logic-heavy. React’s job is to help with the UI and not with the underlying business logic.

The problem

On a single page React app, which uses Material-UI components, introduce a contact form.

My goals were:

  1. keep using Material-UI components like <Textfield>
  2. have very basic validation which I don’t have to write from scratch ( ’cause I am lazy and I make mistakes — or I may want to extend it in the future-or both)
  3. make the form a component that I could reuse on my next project (again, ’cause I am lazy)

The validation part was what got me scratching my head the most. All I needed was to validate an email address and mark a couple of fields as required. Keeping in mind that the app had no back end, it seemed obvious that built-in HTML5 form validation should be enough. I am sure there is a way to do this but I just did not find it (please enlighten me, dear reader!).

Long story short, I figured that if you want to keep all the goodies that come from Material-UI and remain within the React way of doing things, then you have to compromise and increase the complexity a little bit. There are js libraries that deal with forms which addressed my problem. The React documentation suggests Formik, which I found to be the most relevant. Formik stood out because of its simplicity and also because of the video of its author (Jared Palmer) which made a lot of sense. Not the most scientific way of choosing tools, but when you want results fast, you have to also go with gut feeling. Formik did smell right!

Jared Palmer presenting Formik

Validation

There are a few js libraries for validating data, but yup seemed very simple and was also recommended by Formik. Once formik was introduced, it was very easy to plug any validation library, so I was not too concerned about extensively researching it. I am certain that ajv and joi would have done for my task (which was very simple).

Presentation

We want to stick with Material-UI yet we want to plug in some business logic that takes care of validation and error messages. The TextField API is designed so that it allows us to control the data it displays while it deals with the presentation of the data. The API allows for the value, the onChange, and the onBlur event handlers, the helperText and the error flag to be controlled from outside the component.

TextField example

Formik deals with how the data will be passed around the form (and most importantly through the validation). Join the 2 and you have a great looking form with validation that is easy put together and maintain. Most importantly, the presentation layer (Material-UI) is completely separate from the form handling layer (Formik). We could easily swap either without affecting any.

Here is the code:

Before copy — pasting please notice just one thing: the form attributes (email, name, comment) are not stored in my component’s state!!!! Sure, I keep a couple of variables in the state (open, isSubmitionCompleted), but both have to do with the presentation of the component. Formik has encapsulated all the form attributes. Kind of cool.

As a footnote: the endpoint is an AWS lambda function which generates an email with the contact form data.

--

--