React Hook Form - Resetting "isDirty" without clearing form?
Asked Answered
O

6

31

Basically what the title says. When I submit the form I'm checking if the login is successful, if not it displays a message. However, when the user starts to type I want this message to go away.

Kinda assumed isDirty would be cleared once the form was submitted, but it remains dirty. I can call reset from the onSubmit, but that will clear the forms' content - which I don't want.

Ideas?

Olnton answered 18/9, 2020 at 9:56 Comment(1)
Please include the relevant code.Brawn
S
50

You can send a new set of values to the reset. Since you do receive a set of values in the submit handler, you could connect both functionalities in the following way:

const {reset, handleSubmit, formState} = useForm();
const {isDirty} = formState;

const handleFormSubmit = (values) =>
{
    //This would be the call where you post your info
    fetch('google.com')
    .then(response => console.log('response', response))
    .finally(() => reset(values));
}

Notice the reset(values) in the example above, which will reset your form to the values it tried to submit. Thus, rendering isDirty back to false.

This is a rather common need in forms that do not reload or redirect after sending the information, so I assume they will eventually create a cleaner way to do it.

Soandso answered 25/9, 2020 at 9:5 Comment(1)
Warning: reset also changes the id from the fields useFieldArray, so will cause remounting of those components (only some use-cases will be affected). It's discussed more here. The answers below (reset({}, { keepValues: true });) don't seem to have this issue.Linis
P
17

resetting in a useEffect() will work, but useEffect() should not be used for such things. see all the discussions around react 18 and useEffect() running twice.

just call

reset({}, { keepValues: true });

in your handleSubmit function at the end. no need to provide all values if you just want to keep the current ones.

Precontract answered 7/1, 2023 at 20:45 Comment(1)
This causes another problem and sets the form to the previous defaults value. Also tried adding keepValues but no effect.Vulgar
T
5

Thanks to this thread and posted by Charlie-Hua, we both solved this by: https://github.com/react-hook-form/react-hook-form/issues/3097

  React.useEffect(() => {
    if (isSubmitSuccessful) {
      reset({}, { keepValues: true });
    }
  }, [isSubmitSuccessful, reset]);
Ticknor answered 6/1, 2023 at 11:5 Comment(0)
M
3

to set the current state as not dirty you should reset, send false to other params and send the current state as values:

reset(watch(), { keepValues: false, keepDirty: false, keepDefaultValues: false });
Mcconnell answered 7/12, 2023 at 6:24 Comment(0)
L
2

To reset the isDirty state without interfering with the form's values or default values, one example would be (being explicit):

reset(undefined, {keepValues: true, keepDirty: false, keepDefaultValues: false});

Example with React.useEffect() hook:

I want to keep the submitted name and filter values and the ability to reset to the original defaultValues, while resetting isDirty:

const { reset, formState: { isSubmitSuccessful } } = useForm({
  defaultValues: {
    filter: "",
    category: "",
  }
});

React.useEffect(() => {
  if(isSubmitSuccessful) {
    reset(undefined, {keepValues: true, keepDirty: false, keepDefaultValues: false});
  }
}, [isSubmitSuccessful, reset]);

The useForm Documentation explains under props the different options available for reset(). They can also be referenced in the project's TypeScript Declaration

Infered type:

const reset: (values?: any, keepStateOptions?: Partial<{
    keepDirtyValues: boolean;
    keepErrors: boolean;
    keepDirty: boolean;
    keepValues: boolean;
    keepDefaultValues: boolean;
    keepIsSubmitted: boolean;
    keepTouched: boolean;
    keepIsValid: boolean;
    keepSubmitCount: boolean;
}> | undefined) => void
Lyndseylyndsie answered 21/7, 2023 at 23:58 Comment(0)
W
0

This worked for me:


  const {
    handleSubmit,
    watch,
    reset,
    setValue,
    getValues,
    formState: { isValid },
  } = methods;

reset(getValues(), { keepValues: true });

// or just

const submit = async (data: VitalsForm) => {
  reset(data, { keepValues: true });
};

// which is the same

The reason I did this is because I have a very complicated form that uses watch() to update some values.

Trying

reset({}, { keepValues: true });
// or
reset(undefined, { keepValues: true });

will make my useEffect() run twice and make the form dirty again, because it has setValue() inside it. It seems like watch() is triggered twice with 2 different values, one is the default/undefined (created by the {} or the undefined in the reset function) and the second is the real one. That makes my setValue() change the value twice.

It seems like a very weird behavior that is native to react-hook-form but I'm still looking into it.

Weatherford answered 2/6, 2024 at 14:28 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.