react-hook-form: Form is dirty even though dirtyFields is empty

Describe the bug Form is dirty when it should not be dirty

To Reproduce Steps to reproduce the behavior:

  1. Focus on first input
  2. Click elsewhere
  3. See isDirty: true

Codesandbox link (Required) https://codesandbox.io/s/react-hook-form-dirty-y7x03?file=/src/App.tsx

Expected behavior Expected isDirty to be false since nothing is changed and dirtyFields is empty

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 5
  • Comments: 24 (18 by maintainers)

Most upvoted comments

I had the same issue, so instead of using isDirty, I’m checking if the dirtyFields object is empty:

export const isEmpty = (obj: object) => {
  return Object.keys(obj).length === 0;
}

if(!isEmpty(dirtyFields)) { "insert code here" }

Seems to be working fine

You can build ur own 😃 getValues() and do ur own compare 👌

Does this fix issue when isDirty = true when default values has more values than there are inputs?

eg. defaultValues { name: “John”, middle: “”, surname: “Doe”} getValues { name: “John”, surname: “Doe”}

this would set isDirty to true

I have an issue when field is not always present (like Middle name) in the form but default value is set in case it is needed then isDirty flag is always true. I have found the cause to be deepEquals function…

nope, it’s a deep equal and its expected behavior.

Does this fix issue when isDirty = true when default values has more values than there are inputs? eg. defaultValues { name: “John”, middle: “”, surname: “Doe”} getValues { name: “John”, surname: “Doe”} this would set isDirty to true I have an issue when field is not always present (like Middle name) in the form but default value is set in case it is needed then isDirty flag is always true. I have found the cause to be deepEquals function…

nope, it’s a deep equal and its expected behavior.

But should we use deepEqual for isDirty? It makes isDirty flag unusable in highly dynamic forms, which is half of them in my current project. I wish I could supply my own isDirty function.

looks like missing defaultValues:

defaultValues: { foo: "", bar: '' }, we are doing deepCompare with defaultValues, and can’t assume input’s value.

Oof, I just hit this issue and was absolutely convinced that it must be a bug, until reading this. I can understand the logic about missing defaultValue. But surely if a field is considered dirty, then it should appear in the dirtyFields object? By definition, isDirty cannot be true while dirtyFields is empty.

If this is really expected behavior as described above, then at the very least it’s not clear or obvious and feels more like tribal knowledge. For now, I’m resorting to @rygo11’s workaround.

Does this fix issue when isDirty = true when default values has more values than there are inputs?

eg. defaultValues { name: “John”, middle: “”, surname: “Doe”} getValues { name: “John”, surname: “Doe”}

this would set isDirty to true

I have an issue when field is not always present (like Middle name) in the form but default value is set in case it is needed then isDirty flag is always true. I have found the cause to be deepEquals function…