How to check if Formik values have changed on submit

Michal Ševčík
2 min readOct 11, 2018

--

So I am using Formik for building forms in React. But there’s a missing piece of functionality. That is when you submit a form and you don’t know if the submitted data have changed compared to the initial form values. Or maybe you need access to all the initial values on submit, not just a flag indicating whether or not the data have changed.

But why?

To give you a picture why would one need such a thing.

  1. You have an application that requests users to scan their ID or some other document proving their identity (driving license, passport, Star Wars Membership card, …) when registering.
  2. The user scans the document
  3. The scanned ID is send to BE to extract values from it (firstname, lastname, address, …)
  4. Extracted values are sent back to FE and shown in your form
  5. The user can either submit the form with prefilled values as is or update the values (e.g. the OCR didn’t do good job).
  6. And you want to know that the values have been modified so you can flag the account being created, e.g. for manual check.

or maybe you just want to save yourself a request when nothing has changed and a form is submitted.

How to do it

So how do we actually get to access initial values on submit? There’s definitely a bunch of solutions, but I will show you the one I’m happy with.

I’ll assume you’re using redux for state management, but this will work with any other state management library. Also I’ll take advantage of three recompose library utilities, namely compose and withHandlers, shallowEqual.

import { connect } from 'react-redux';
import { compose, withHandlers, shallowEqual } from 'recompose'
import { Formik, Form } from 'formik'
const FooForm = ({ initialValues, onSubmit }) => (
<Formik onSubmit={onSubmit} initialValues={initialValues}>
{({ isSubmitting }) => {
<Form>
...
<button type="submit">Submit form</button>
</Form>
}}
</Formik>
)
const withStore = connect(
(state) => ({
initialValues: {
firstName: state.auth.firstName,
lastName: state.auth.lastName
}
}},
(dispatch) => ({
onSubmit: (initialValues, values, formActions) => {
const hasChanged = !shallowEqual(initialValues, values)
// do whatever you wish, most probably dispatch
// an action
}
})
)
const enhance = compose(
withStore
withHandlers({
onSubmit: props => (...args) => {
props.onSubmit(props.initialValues, ...args)
}
})

)
export default enhance(FooForm)

In order to understand how withHandlers works, take a peek in recompose’s library documentation. Basically it’s a high order component that takes as a parameter a map of high order functions (function returning function).

That’s it, basically with 4 lines of code you’re able to access initialValues in your onSubmit handler.

--

--