62

In Formik, how to make the Reset button reset the form only after confirmation?

My code below still resets the form even when you click Cancel.

var handleReset = (values, formProps) => {
    return window.confirm('Reset?'); // still resets after you Cancel :(
};

return (
  <Formik onReset={handleReset}>
    {(formProps) => { 
      return (
        <Form>
          ...
          <button type='reset'>Reset</button>
        </Form>
      )}}
  </Formik>
);
Aximili
  • 28,626
  • 56
  • 157
  • 216

9 Answers9

157

Hello @Aximili you can use resetForm in onSubmit.

onSubmit={(values, { resetForm }) => {

      // do your stuff 
      resetForm();

}}

what resetForm can do?

Imperatively reset the form. This will clear errors and touched, set isSubmitting to false, isValidating to false, and rerun mapPropsToValues with the current WrappedComponent's props or what's passed as an argument. The latter is useful for calling resetForm within componentWillReceiveProps.

Kruupös
  • 5,097
  • 3
  • 27
  • 43
patelarpan
  • 7,188
  • 2
  • 20
  • 25
21

I'm not completely certain, but I think you will have to write your own reset function without a button with a reset type. Something like this:

const handleReset = (resetForm) => {
  if (window.confirm('Reset?')) {
    resetForm();
  }
};

function Example() {
  return (
    <Formik initialValues={{ value: 1 }}>
      {formProps => {
        return (
          <Form>
            <Field name="value" type="number" />
            <button
              onClick={handleReset.bind(null, formProps.resetForm)}
              type="button"
            >
              Reset
            </button>
          </Form>
        );
      }}
    </Formik>
  );
}

If you really want to use onReset, I think the only way is to throw an error. The Formik source code seems to indicate resetForm() will be called no matter what your onReset() function returns.

const handleReset = () => {
  if (!window.confirm('Reset?')) {
    throw new Error('Cancel reset');
  }
};

function Example() {
  return (
    <Formik initialValues={{ value: 1 }} onReset={handleReset}>
      {formProps => {
        return (
          <Form>
            <Field name="value" type="number" />
            <button type="reset">
              Reset
            </button>
          </Form>
        );
      }}
    </Formik>
  );
}

I would still go with the first solution though personally.

Ciarán Tobin
  • 7,306
  • 1
  • 29
  • 45
  • 1
    Thank you MadScone. Yeah you could do that, but Formik already have `onReset`, so I thought there should be a way to do it there – Aximili Apr 10 '19 at 23:36
  • I updated my answer with a possible solution if you really want to use `onReset`. – Ciarán Tobin Apr 11 '19 at 09:09
  • Thanks a lot for looking at the source code, that looks like a Formik limitation. I'll go with your first solution :) – Aximili Apr 12 '19 at 03:01
16

I understand OP's question was for Formik.

However, for anyone using useFormik hook and wanting to clear form on 'reset' button click, here's one way to achieve that.

<button type="reset" onClick={ e => formik.resetForm()}> Reset</button>

Anil_M
  • 10,893
  • 6
  • 47
  • 74
5

in 2023 formik.resetForm(); this worked for me.

here is the complete code for onSubmit event

  onSubmit:(values)=>{
const name = values.name;
      const mobile = values.mobile;
      const website = values.website;
      const service = values.service;
      const msg = values.msg;
  
axios.post('/api/SendContactForm', {name, mobile, website, service, msg})
      .then(function (response) {
           //console.log(response);
              toast.success(' Thanks for the message. We will contact you asap.');
              formik.resetForm();
          })
          .catch(function (error) {
            console.log(error);
            formik.resetForm();
            toast.error(error.message || error.statusText);
          });
     
  
      }
  
  });

  • You can simplify the code by adding a `finally` callback handler to the Promise that resets the form, so you don't need to do it twice. – Peter Hägg Feb 08 '23 at 15:48
4

Here is the solution:

<Formik
initialValues={initialValues}
onSubmit={async (values, { resetForm }) => {
  await onSubmit(values)
  resetForm()
}}>

Reset the form on submit immediately.

I'm not using a custom wrapper around Formik.

Lalit Tyagi
  • 264
  • 2
  • 10
  • 1
    this is great if you don't need a button like the OP requested. I ended up doing similar to this, but in the 'const onSubmit' declaration. And I wanted to keep the filled form data, so just did actions.setSubmitting(false) rather than reseting the whole form. – C-Note187 Jan 03 '23 at 17:21
3

My issue was I did not wanted to use window.confirm(). I wanted to use my own modal so I used

useFormikContext()

You can create a function component like this

let resetPresForm = {};// You will have to define this before useEffect

const ResettingForm = () => {
    const { resetForm } = useFormikContext();
    resetPresForm = resetForm; // Store the value of resetForm in this variable
    return null;
};

Now Import this function component inside your

<Formik>
     <button type="button" onClick={() => { setShowResetModal(true) }} className="comman-btn">Reset</button>
     <ResettingForm />
</Formik>

Now on modal component confirm you can

const resetPrescriptionForm = () => {
    setShowResetModal(false);
    resetPresForm();
}

Reference

Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
ayu.sheee
  • 51
  • 3
1

I used actions.resetForm() and It resolved the problem.

onSubmit={(values, actions) => {

     actions.resetForm();

}}
Shrip
  • 101
  • 1
  • 6
1
     onSubmit: async (values, actions) => {
    actions.resetForm();
  },

You must add two parameters and use second parameter. So you can try actions.resetForm();

0

In my case I created a Formik event of onReset={handleFormReset} & inside form props, passed handleReset for onReset event of form like this-

            <Formik
            onSubmit={handleFormSubmit}
            initialValues={initialValues}
            validationSchema={checkoutSchema}
            onReset={handleFormReset}
        >
            {({
                values,
                errors,
                touched,
                handleBlur,
                handleChange,
                handleSubmit,
                handleReset
            }) => (
                <form onSubmit={handleSubmit} onReset={handleReset}>

Then I created a button with type='reset', like

<Button type="reset" color="warning" variant="contained" sx={{ mr: 3 }}>
   Reset
</Button>

Finally, I created the handler function handleFormReset(values), where I emptied the values object if user confirms inside a confirm box.

    const handleFormReset = values => {
    if (window.confirm("Do You Want To Reset?")) {
        values = {};
    }
};