Build React forms and validation with Formik like a boss

I remember whenever I build forms and handle validation of any kind on my own it’s going to end with huge pain and with tears, especially in web development.

Photo by NORTHFOLK on Unsplash

But there are actually smart approaches that simplify the whole process and let you focus on your business logic.

One thing I really love about React is that it allows you to build stuff the way you like, the way that makes most sense for you. While this might end in a catastrophe pretty easily, there are actually pretty great patterns for specific use cases out there.

This leads us to forms and validation in React. There are many routes we can take when it comes to validation. Here are a few methods that come to my mind right now:

Possible solutions

  1. Store input in the container component’s state. Validate them after the user hits submit and before you actually submit the data to a remote endpoint.
  2. Store input in the container component’s state or React Redux and validate them on the fly when the user manipulates the inputs.
  3. Use a third party library that already ships form, input and error components out of the box, plus hook up third party validation on top of it.

As I said in the beginning, you may choose any method that suits you best since React is not opinionated in comparison to many other full fledged web frameworks like Angular.

In my experience, I think using a third party library like Formik which already deals with stuff I don’t want to bother about works best for my projects since I’m able to entirely focus on my business logic.


Getting into it

A few hours ago, I wanted to give it a shot and decided to make use of Formik as form composer and Yup as validator in our company’s playground project Doki (= donation kiosk), an office piggy bank companion written in React and TypeScript that I started for students like me.

This is the donation submission page. As we can see, there’s no client side validation yet. Let’s change that with Formik and Yup.

The current form looks more or less like this. There’s no business logic involved yet, just plain FormInput components written in TypeScript that embody a label as header and input.

I could directly hook up the values into the FormInput presentation components and add a new event handler to my submission button. But since that could end up nasty, we’ll be using Formik. We are going install Formik and Yup to our React project first and transform the whole form:

yarn add formik yup @types/yup

First of all, let’s add all required import statements to our form component file:

import { Formik, FormikActions, FormikProps, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';

Looks good to me. It’s time to compose our view model for the form. We have two inputs right now, one that contains the donator’s name and another that contains their pledge amount (a positive number, obviously). We add an interface that defines the form similar to what we do with React props and states in TypeScript:

For our render method, let’s change the TSX markup like this:

We’ve set initial values for the form component and refer to them from our Formik container component that ships with Formik. This component deals with the state, props, actions and connectors that are required to build your form.

Next up, we implement our inner render method for our brand new Formik component that contains various inputs, labels and the submission button:

There’s a bunch of stuff going on so let me highlight some stuff real quick:

  • The render method accepts a bag that contains your form’s properties and much more. Basically all objects you require to build a form.
  • The Field component is shipped by Formik and basically wraps your input tag. Awesome stuff: the input’s HTML name reflects the property name of your form’s view model (looks similar to form HTTP requests, eh?).
  • The ErrorMessage component is shipped by Formik as well and allows you to display error messages in any component you want. This form uses div as parent component. You may also specify a custom component and apply some CSS flavor onto it as long as it renders the component’s child property within the inner HTML. 
    Also, this makes use of the HTML name attribute as well. Formik is going to match the error message to the respective ErrorMessage component.

Now it’s time to add some validation to it. As much as it sounds like a huge pain in the butt, it’s actually pretty simple with Formik and Yup.

Yup allows you to set a validation schema by using a fluent interface. Let’s create a property for it:

Remember when I said that we introduced types for our form view model? This is being considered in here and in addition to that we also set validation rules and their error messages.

Looks great so far, now let’s add the submission handler and we’re done:

Don’t forget to refer to our new handler

Last but not least, let’s bring it to life:

Tada 🎉 — I guess it wasn’t too tough to implement, and I think Formik lives up to its promise, “Build forms in React, without the tears 😭”, that is.

And of course if you ever get stuck, Formik has a great documentation just like Yup.

and of course, there’s always StackOverflow as fallback solution (https://www.reddit.com/r/ProgrammerHumor/comments/atjfj8/)

I hope you’ve enjoyed this article. If you do, I’d be happy if you share this article, check out my other articles and let me know what you think. You can also visit my website for my past articles and projects.