Formik: Check what fields have changed in submit

Created on 22 Oct 2017  路  19Comments  路  Source: formium/formik

How to check what fields changed in handleSubmit?

Question

Most helpful comment

You can compare initialValues and values within handleSubmit/onSubmit

All 19 comments

Compared to what? Can you provide more details?

I mean touched field in handleSubmit

When submitting, Formik sets all fields as touched https://github.com/jaredpalmer/formik/blob/master/src/formik.tsx#L475, so error messages can be shown properly.

My case is that I want to only update fields that changed, because I have different API request for each field

Then you can maybe check values inside onSubmit and if it's not empty, send a request?

@prichodko I have default values from server. Well I can check each value to old values. And send values that changed

I'm having a similiar issue -- I think the idea is to somehow add a dirty prop for each form field

You can compare initialValues and values within handleSubmit/onSubmit

@goodmind, This lib is helpful: deep-object-diff

Probably a dumb question but how do you access initialValues inside onSubmit when using <Formik initialValues={} render={} onSubmit={}>?

Wouldn't this be passed in as a prop that you would have access to from within onSubmit on this.props?

True. I'm fumbling around so could be something obvious I'm missing:

The data I get from the server is not always in the required shape of a field, thus I'm doing some transformations in initialValues (Draft.js example below). If I can't pass initialValues, I'd have to repeat the transforms in onSubmit so I'm comparing against the same thing. Maybe initialValues is the wrong place and I should just do transforms further up in the tree?

const Form = ({ post: { content } }) => (
  <Formik
    initialValues={{
      content:
        content && !isEmpty(content)
          ? new EditorState.createWithContent(convertFromRaw(content))
          : new EditorState.createEmpty()
    }}
    onSubmit={{}}
    render={{}}
  />
)

I don't actually need to compare Draft.js fields, its just the best example to show transformations.

Yes, I think you need to transform in 2 places.

Brilliant. Thank you for Formik - it's been a great experience.

Fun Fact: Formik initially had a prop called mapValuesToPayload. My idea was to centralize these sort of transforms in one place so you knew where to look. It was redundant because it can just go at the top of handleSubmit/onSubmit, but the idea was to keep things organized.

I for one appreciate the narrow focus of Formik, you could easily end up recreating the world in utility functions. Just that when you're new to something its not always easy to know what the package has taken on and what they have deliberately left to the user (Not unique to Formik or a criticism).

I wrote an article How to check if Formik values have changed on submit, this may help someone https://medium.com/@MelkorNemesis/how-to-check-if-formik-values-have-changed-on-submit-2c6ee89992ec

Why not just check for form.dirty in onSubmit, like this:

// useState for initialValues to keep updating it using an useEffect hook as data on server changes
const [initialValues, setInitialValues] = useState({foo: "bar"});

const form = useFormik({
  enableReinitialize: true, // required to have dynamic initialValues
  initialValues,
  onSubmit: async (values, { setErrors }) => {
    console.log({ values, dirty });
    if (!dirty) return;
    // else do stuff
    setInitialValues(values); // just for testing
  },
});
const { errors, touched, getFieldProps, handleSubmit, dirty } = form;

Seems to be working fine for me, @jaredpalmer let me know if this technique has any caveats I should be aware of.

import React from 'react'
import { useFormik } from 'formik' 

const Component: React.FC = () => {
  const { handleSubmit, getFieldProps, dirty, isValid } = useFormik({
    initialValues: { email: '[email protected]' },
    onSubmit: Promise.resolve,
    validationSchema: yup.string().email(),
    validateOnMount: true
  })

  return (
    <form submit={handleSubmit}>
      <input {...getFieldProps} />
      <button disabled={!dirty || !isValid}>Submit</button>
    </form>
  )
} 

Was this page helpful?
0 / 5 - 0 ratings

Related issues

najisawas picture najisawas  路  3Comments

ancashoria picture ancashoria  路  3Comments

jeffbski picture jeffbski  路  3Comments

jordantrainor picture jordantrainor  路  3Comments

Jucesr picture Jucesr  路  3Comments