How Harness upgraded Formik Forms to v2

Ishant Mehta
Harness Engineering
5 min readJul 8, 2022

This post will walk you through the Formik forms in React. We will understand Formik and then focus on Harness Journey on migrating Formik library from v1 to v2.

What is Formik

Forms are really verbose in React. To make it worse, helpers do some logic, and impact the performance badly. Formik is a small library to solve the 3 most annoying problems and reduce boilerplate.

  • Getting Values in and out of form state
  • Validation and error messages
  • Handling form submission

Want to learn more about Formik: do checkout Formik docs

Why we use Formik

At Harness, we use forms at scale. Our forms have different kinds of fields, including input, textarea, select dropdowns, and creatable select. Maintaining the state of these components everywhere was not scalable. Here comes Formik to the rescue.

Usage Examples

Why we migrated from v1 to v2

Formik v1 uses React 15. It doesn’t support the famous React Hooks. After the React 16.8.x release, Hooks came into play. The Formik team released a v2 version, which enables us to use formik hooks and take advantage of improved performance.

Our Journey

Migrating from v1.x to v2.x in a big codebase is a complex task. The task was broken down into smaller subtasks to make it doable.

Formik Migration Guide changes

  • Typescript Changes: This was a straightforward task, which involved renaming a few imports. For example, rename import of FormikActions to FormikHelpers
  • Formik API Changes: There are few breaking API changes including
    - resetForm: v1 don’t expect any argument. Now it accepts values, errors and status separately
    - validate: Our code used “throw keyword” to return errors. Now we can return a Promise which can reject in case of error
  • Deprecation Warnings: render props have been deprecated

Code Specific Changes

There were few code level specific changes, which were not upfront mentioned in the doc.

  • By default shouldValidate is true in the setFieldTouched function. This is useful for creating custom input blur handlers. In our case, the validation is running twice, first with latest data and then with last state data, and leading to obsolete data being present in the UI. We explicitly prevented this validation by passing 3rd argument as false
  • Validation runs on obsolete data when calling setFieldValue multiple times consecutively. Don’t use setFieldValue multiple times consecutively, instead use setValues to batch the updates. Also we need to pass validateOnBlur=false where setFieldTouched is being called
  • Few of our Jest test cases were giving an error.

TypeError: Cannot read property ‘validateOnChange’ of undefined

Here the testing form components are not wrapped in Formik. We solved it by wrapping it in Formik

  • If you don’t want any validation in some scenario, use validationSchema as undefined instead of an empty object
  • Use initialValues as an empty object instead of null

Challenges

The change is across the entire codebase, including mono-repos, this took more than 3 weeks. Our main challenges were

  • Rebasing — We had to rebase every other day to keep the changes up-to-date. We made sure new master code check-ins are adapting to Formik v2 changes
  • Testing — Are we sure this migration will work smoothly in QA and production environments? This was one of the blockers for releasing this migration

To test the changes, following steps were being followed

  • We took leverage of a good number of test cases written in the UI codebase. We ran all Jest test cases across modules. If any test fails, we reproduce it locally in the UI and see if it’s a test case issue or genuine code issue. We fixed all such failures(~50 were reported in this step). This gave us good confidence
  • We also took leverage of Selenium automation. We ran it on pre-qa environments and found out a few issues(~5 were reported here)
  • The whole team came together and tested their module changes in a pre-qa environment manually(~0 issues reported here)
  • We merged the changes in the QA environment. After rigorous testing, we got only 2 issues, which were missed due to test case coverage
  • We are proud to share that we got ZERO customer issues due to this Formik Migration

Learnings

  • Documentation — While upgrading any library, it’s very good to first go through the documentation and then proceed with the changes. This step made the migration process smooth. For example, When we got issues related to obsolete data, all thanks to the documentation, else we would have been using hacks to fix this validation
  • Good Test coverage — It was due to our solid test coverage (both in UI and Selenium), we were confident to merge the migration changes. Else, we would have got more than 55+ bugs after the merge
  • Teamwork — This complex task across 8+ modules is not one man’s job. Point of Contact from all teams came together, helped us test and release this upgrade

Join Harness community on slack to speak to our engineering team

--

--