Building forms using Formik with the React Hooks API and TypeScript

JavaScript

The Formik library keeps on growing and attempts to keep up with the React community. Formik, since version 2.0, has a built-in set of hooks. In this article, we go through all of them. We also look into how to use Formik with TypeScript.

The basics of Formik with TypeScript

Form handling in React might require quite a bit of code. Therefore, there are quite a few approaches out there to help us with that. Formik deals with three essential tasks:

  • Handling the values inside of a form
  • Validating the data
  • Dealing with the form submission

We’ve dealt with the basics of Formik in the past. If you are interested, check out Writing React forms with Formik. Validating data using Yup. Therefore, in this article, we focus on TypeScript support and the Hooks API.

The Formik library is built with TypeScript. Thanks to that, we always have the newest typings. The first thing to look into is the   component. It acts as an initializer for our form. When discussing the TypeScript integrations, we need to look into the   and the   props.

initialValues & onSubmit

The   prop represents the initial values of our fields. Even if our form starts as empty, we need to initialize all fields with initial values. Otherwise, React complains in the console that we’ve changed an input from uncontrolled to controlled.

The   prop gets called as soon as we submit our form. Inside of it, we have access to the form values, among other things.

The important part is that the   component is generic. We’ve looked into generic React components previously. If you are interested, check out Functional React components with generic props in TypeScript

In the typings, we can see that   and the values inside of the   have the same type. It means that when we submit the form, we can expect the same set of properties that we’ve provided as  .

Let’s look a bit closer into the typings of the   prop:

The interesting thing is that it can return a promise.

When we start submitting our form, the internal   value is set to . If we return a promise from our  handler, the   value changes to   when the promise resolves or rejects.

useContactFormManagement.tsx

If you would like to get more insight on how to design React hooks such as the one above, check out JavaScript design patterns #3. The Facade pattern and applying it to React Hooks

With our   hook, we now have everything we need to create a basic contact form.

The useField() hook

Above, we use the   component in a very basic way. It automatically hooks up inputs to Formik. It has quite a few possibilities of customization, but we can use the   hook instead.

With   hook, we can create more advanced inputs that look like we want them to. The most straightforward way of using the above hook is to provide it with the name of the input. It returns three properties packed in an array:

We can also provide the   with the same arguments as the Field component. For a full list, check out the documentation.

The   property is designed in a way that allows us to pass it straight to a   tag. It holds values such as  , and  .

The   property holds relevant metadata about the field. An example of such is an   or  .

The   contain helper functions that allow us to interfere with the field directly:  , and  .

A full description of the above arguments can be found in the documentation.

The above example is quite a basic custom Formik component. Please note that the   function is also generic so that we can pass it the type of the value. This way, we can improve the types of applications even more.

We can also use the   hook to integrate libraries such as Material-UI and Ant Design with Formik. We can also use one of the 3rd party bindings to do the integration for us.

The useFormikContext() hook

The   can be very useful when we need to add some more advanced functionalities to our form. Therefore we can have access to the state of our form and all of its helpers through React Context.

To use the   hook, we need to have the   component higher in the component tree, or use the withFormik higher-order component

An example of a use-case is creating conditional fields.

In the above component, we show the   only if the   checkbox is checked. Since the   is also generic, we can supply it with the interface describing all of the form fields.

The Formik props carry all of the props of the   component. The official documentation also has a useful use-case mimicking the Stripe’s 2-factor verification form, so it is worth checking out.

The useFormik() hook

Formik uses the   hook internally along with React Context to create the   component. Even though that’s the case, Formik exports it for advanced use-cases. For example, we can use it if we want to avoid the usage of React Context in our application.

Summary

In this article, we’ve gone a bit deeper into Formik works and how to utilize that using the Hooks API. We’ve also talked a bit about how to use Formik with TypeScript. By using  , and   hooks, we can create quite advanced forms. We can also build field components that we can reuse across our application.

Subscribe
Notify of
guest
6 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
ronkot
ronkot
3 years ago

Thank you! Just found your articles and I’ve to say that these are amongst the best ones. I got answers to many of my questions like “how do all these different formik hooks differ from each other”? Great job!

reactiveCraze
reactiveCraze
3 years ago
Reply to  Marcin Wanago

For a more complete use case, please also provide submitContactForm.tsx

vijay potluri
vijay potluri
3 years ago
Reply to  Marcin Wanago

For a more complete use case, please also provide submitContactForm.tsx

Luis Schweigard
Luis Schweigard
3 years ago

Great article!
I was just wondering: should I use the Formik-Component or the useFormik-Hook for normal forms? I don’t quite understand the advantages of using the Component!

JP developer
JP developer
2 years ago

Thank you Marcin for posting this. The official docs don’t go deep enough, you saved me a lot of headache.