Tutorial: How to Reset Formik Form
Jasser Mark Arioste
In one of my projects, I recently had to implement a functionality where in the backend/cms where the save button will be disabled after submitting the changes. This can be done by using the really awesome react library called Formik .
What is Formik?
Formik is a relatively small react library used for managing forms in react. It allows us to build forms and manage form state without the headache. This is especially useful if you’re building a huge form like for example in the backend Edit user, Edit post, etc. A post or a user has many properties just managing the errors or state of the page is borderline impossible without something like Formik.
One thing I like about Formik is it’s simplicity when integrating with UI libraries like MUI.
How to reset the form and disable the save button?
One way to disable the save button is to check if the form is dirty using dirty flag from formik. dirty will be set to true when there’s any change in the initial state of the form. The way to modify dirty is by calling resetForm helper function provided by Formik .
In this tutorial I’ll be discussing the following scenarios:
- resetting the form inside onSubmit function
- Resetting the Form when using <Formik> provider
- Resetting the Form when using isFormik hook
Scenario 1: Resetting the form inside onSubmit function
In simple scenarios, we can just reset the form inside onSubmit . For example let’s see the form below:
//EditUserForm.tsx
import { Field, Form, Formik } from "formik";
import React from "react";
import SaveButton from "./SaveButton";
const EditUserForm = () => {
//just a mock save function, let's pretend this calls the server
const save = async () => {
return {
error: Math.random() > 0.5 ? "failed to save" : "",
};
};
return (
<Formik
onSubmit={async (values, helpers) => {
const { error } = await save();
// reset the form if it is saved successfully
//now the initial state will be the values submitted.
if (!error) {
helpers.resetForm({
values,
});
}
}}
initialValues={{ name: "John Doe", email: "johndoe@gmail.com" }}
>
<Form className="flex flex-col gap-2 max-w-lg bg-base-200 shadow-md p-10">
<h1 className="text-xl"> Edit User</h1>
<Field
name="name"
type="text"
placeholder="name"
className="input input-bordered"
/>
<Field
name="email"
type="email"
placeholder="email"
className="input input-bordered"
/>
{/* custom save button */}
<SaveButton />
</Form>
</Formik>
);
};
export default EditUserForm;
//SaveButton.tsx
import { useFormikContext } from "formik";
import React from "react";
const SaveButton = () => {
//access formik context to check if the form is dirty.
const { dirty } = useFormikContext();
return (
<>
<button type="submit" className="btn btn-primary" disabled={!dirty}>
Save
</button>
</>
);
};
export default SaveButton;
In the codes above we have two components, EditUserForm and SaveButton . In this specific use case, The submit button has to be disabled when there are no changes to the fields and when the save is successful. It only becomes enabled when the user edits the fields.
Let’s see it in action.
Notice the save button. Once we click save the form is reset but we’re using the updated values as the initial values. We achieved this by passing an { values } option to the resetForm method. If we want to reset the form using the original values, we don’t have to pass anything to resetForm .
With this I’ve solved my use case.
Now let’s talk about other use cases. Let’s say we don’t want to reset the form inside onSubmit and just have a reset button inside the form so that the user can go back to the initial values. There are two ways to use formik and let’s discuss how to achieve this in both ways:
Scenario 2: Resetting the form when using <Formik> provider.
Almost 100% of the time, I use <Formik> provider when creating forms because it has a clear boundary of the scope/context of form. You can have nested <Formik> provider components and there will be no problem.
So in order to access resetForm helper, there are two ways:
- Using renderProps
- Creating a new component and using useFormikContext
Using renderProps to access Formik Context
Let’s modify our form component and add a reset button beside the save button. The reset button should only be enabled if the form is dirty and when click it resets the form to it’s original state.
//EditUserForm.tsx
import { Field, Form, Formik } from "formik";
import React from "react";
import SaveButton from "./SaveButton";
const EditUserForm = () => {
...
return (
<Formik >
...
{/* we can use render props to get a hold of the formik context */}
{({ dirty, resetForm }) => {
return (
<Form className="flex flex-col gap-2 max-w-lg bg-base-200 shadow-md p-10">
<h1 className="text-xl"> Edit User</h1>
<Field
name="name"
type="text"
placeholder="name"
className="input input-bordered"
/>
<Field
name="email"
type="email"
placeholder="email"
className="input input-bordered"
/>
<div className="flex gap-2 ">
<button
className="btn btn-outline btn-error"
disabled={!dirty}
onClick={() => resetForm()}
>
Reset
</button>
<SaveButton />
</div>
</Form>
);
}}
</Formik>
);
};
export default EditUserForm;
This already gives us the functionality we need but I prefer refactoring it using next method since it’s a bit cleaner than using renderProps.
Creating a new component and using useFormikContext
Let’s create a new component called ResetButton.tsx and use useFormikContext hook to access the form state and helper functions from inside the component.
//ResetButton.tsx
import { useFormikContext } from "formik";
import React from "react";
const ResetButton = () => {
//access formik context to check if the form is dirty.
const { dirty, resetForm } = useFormikContext();
return (
<>
<button
type="submit"
className="btn btn-primary"
disabled={!dirty}
onClick={() => resetForm()}
>
Reset
</button>
</>
);
};
export default ResetButton;
Usage inside EditUserForm.tsx
//EditUserForm.tsx
import { Field, Form, Formik } from "formik";
import React from "react";
import ResetButton from "./ResetButton";
import SaveButton from "./SaveButton";
const EditUserForm = () => {
...
return (
<Formik>
<Form className="flex flex-col gap-2 max-w-lg bg-base-200 shadow-md p-10">
<h1 className="text-xl"> Edit User</h1>
<Field
name="name"
type="text"
placeholder="name"
className="input input-bordered"
/>
<Field
name="email"
type="email"
placeholder="email"
className="input input-bordered"
/>
<div className="flex gap-2 ">
<ResetButton />
<SaveButton />
</div>
</Form>
</Formik>
);
};
export default EditUserForm;
Scenario 3: Resetting the form when using useFormik hook
If you’re using useFormik to initialize your form, you can simply call resetFrom from the returned context. It’s just preference but I don’t like to use this method since you have to wire up the fields and form.
//EditUserFormHooks.tsx
import { Field, Form, Formik, useFormik } from "formik";
import React from "react";
import SaveButton from "./SaveButton";
const EditUserFormHooks = () => {
//just a mock save function, let's pretend this calls the server
const save = async () => {
return {
error: Math.random() > 0.5 ? "failed to save" : "",
};
};
const formik = useFormik({
onSubmit: async (values, helpers) => {
const { error } = await save();
if (!error) {
helpers.resetForm({
values,
});
}
},
initialValues: { name: "John Doe", email: "johndoe@gmail.com" },
});
return (
<form
className="flex flex-col gap-2 max-w-lg bg-base-200 shadow-md p-10"
onSubmit={formik.submitForm}
>
<h1 className="text-xl"> Edit User</h1>
<input
name="name"
type="text"
placeholder="name"
className="input input-bordered"
onChange={formik.handleChange}
value={formik.values.name}
/>
<input
name="email"
type="email"
placeholder="email"
className="input input-bordered"
onChange={formik.handleChange}
value={formik.values.email}
/>
<div className="flex gap-2 ">
{/* check formik diry and reset form here */}
<button
type="button"
className="btn btn-outline btn-error"
disabled={!formik.dirty}
onClick={() => formik.resetForm()}
>
Reset
</button>
<button
type="submit"
className="btn btn-primary"
disabled={!formik.dirty}
>
Save
</button>
</div>
</form>
);
};
export default EditUserFormHooks;
Final output
Conclusion
We’ve successfully reset our form using Formik by using <Formik> provider or useFormik hook. Formik is very useful when managing forms in react! To learn more about formik you can check the docs here .
Code is available here: https://github.com/jmarioste/formik-reset-form
If you like tutorials like this, please subscribe to our newsletter down below! If not, give it a like or share!
Credits: Image by Pete Linforth from Pixabay


