Caveat: I'm brand new to Javascript/React/react-hook-form so this may be something obvious but when I use non-string default values for fields in a form, the form gets marked as dirty as soon as the field is touched and without any field content being changed.
For example;
import ReactDOM from "react-dom";
import { useForm } from "react-hook-form";
import "./styles.css";
export default function Form() {
//Declare default values
const defaults = {
Firstname: "Fred",
Lastname: "Bloggs",
Age: 30
};
const { register, handleSubmit, formState } = useForm({
mode: "onChange",
defaultValues: { ...defaults }
});
const onSubmit = data => {
alert(JSON.stringify(data));
};
// make sure to read state before render to subscribe to the state update (Proxy).
const { dirtyFields } = formState;
// check your dev console, it's a Set
console.log(dirtyFields);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>Full name</label>
<input type="text" name="Firstname" ref={register({ required: true })} />
<label>Last name</label>
<input type="text" name="Lastname" ref={register({ required: true })} />
<label>Age</label>
<input type="number" name="Age" ref={register} />
<pre>{JSON.stringify(formState, null, 2)}</pre>
<input type="submit" />
</form>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Form />, rootElement);
CodeSandbox link https://codesandbox.io/s/react-hook-form-formstate-dirty-touched-submitted-0rcrj?file=/src/index.js
Clicking in the Age field and then any another field, without making any changes, marks the dirty flag.
I'm guessing that his is because the form treats everything as a string and so in the case of the Age field 30?== "30" and so the form becomes dirty even though nothing was changed in the UI ?
If I change the default to Age: "30" then the form does not become dirty so it seems to confirm it.
I'm trying to use the dirty flag to enable/disable a submit button but this issue is breaking that.
Is there any way around this? How do others handle it?
This is a very interesting catch and I think you are correct about the reason.
A workaround would be to use a <Controller>
or to manually register
the field and apply a transformation with parseInt
.
<Controller
name="Age"
control={control}
type="number"
as="input"
onChange={([event]) => parseInt(event.target.value)}
/>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.