Reputation: 1047
Background:
I have a very long complex form with deep nested objects creating using rhf (react-hook-form
). I want to provide a checkbox at the top of the form which toggles the default values in the fields to assist the user.
Problem
By using rhf, I was able to fill up the defaultValues
using reset
method but now the issue is once I call the reset
method with the defaultValues
, I can't unset the values using the reset
if I provide an empty object.
Things I've tried
I've tried using the setValue
method but it unset only 1 field at once and it'll require recursion to set values for deep-nested object.
Code
Here's a very minimal example of what I'm trying to do.
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { useForm } from "react-hook-form";
const defaultValues = { name: `John Doe` };
const Form = () => {
const [useDefaultValues, setUseDefaultValues] = useState(false);
const { register, handleSubmit, reset } = useForm();
useEffect(() => {
if (useDefaultValues) {
reset(defaultValues);
} else {
reset({}, { keepValues: false, keepDefaultValues: false });
}
}, [useDefaultValues]);
return (
<>
<label>
<input
type="checkbox"
value={useDefaultValues}
onChange={() => setUseDefaultValues((prev) => !prev)}
/>
Use Default values
</label>
<form onSubmit={handleSubmit}>
<div>
<label>Name</label>
<input type="text" name="name" {...register("name")} />
</div>
<input type="submit" />
</form>
</>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<Form />, rootElement);
Codesandbox: https://codesandbox.io/p/sandbox/react-hook-form-reset-form-forked-sxmy8q?file=%2Fsrc%2Findex.js%3A1%2C1-42%2C1
Notice how unsetting the defaultValues
doesn't empty the form again
Upvotes: 0
Views: 2717
Reputation: 273
Your form need to have 3 states. First one containing the default values
. Second one need to have empty value
(actual reset). Third one need to have actual(current) values
which will be handled by react hook form.
An optional object to reset form values, and it's recommended to provide the entire defaultValues when supplied. Source
The Solution to the your Code:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { useForm } from "react-hook-form";
const defaultValues = { name: `John Doe` }; // your own default values
const Form = () => {
const [useDefaultValues, setUseDefaultValues] = useState(false);
const { register, handleSubmit, reset } = useForm({
defaultValues: { name: `` },
}); // actual empty defaul values, you can provide here
useEffect(() => {
if (useDefaultValues) {
reset(defaultValues, { keepValues: false, keepDefaultValues: true }); // reset to defaultValues provided above
} else {
reset(); // reset to actual empty defaul values
}
}, [useDefaultValues]);
return (
<>
<label>
<input
type="checkbox"
value={useDefaultValues}
onChange={() => setUseDefaultValues((prev) => !prev)}
/>
Use Default values
</label>
<form onSubmit={handleSubmit}>
<div>
<label>Name</label>
<input type="text" name="name" {...register("name")} />
</div>
<input type="submit" />
</form>
</>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<Form />, rootElement);
keepValues(true):
Form input values will remain unchanged. Let say we changed the name
to 'abc'
then we call
reset(newValues, { keepValues: true });
The form will still have the old values. The newValues
given here would have no effect.
On the other hand, if we have keepValues(false)
the value will become equal to the newValues
provided in the reset function otherwise (if empty object provided) it become default values.
keepDefaultValues(true):
The form values given in the reset function become the default values. In order to identify any change in the state of the form we use isDirty
. If we have keepDefaultValues(true)
, the isDirty
will compare the default value with the current form value to tell whether the form state has changed or not.
On the other hand, if we have keepDefaultValues(false)
, the isDirty
will compare the new given value in the reset function with the current form value to tell whether the form state has changed or not.
In simple words in addition to this use case, the keepDefaultValues
fucntion can be useful if we want to keep the Default value same as we provided in the beginning by using keepDefaultValues(true)
.
Upvotes: 0