2

I have a React JS form using useForm library.

This is a popular library so I'm not sure this can be a bug but I'm getting into a state which seems incorrect. See the screenshot of the console in chrome below:

Screenshot of console

How can I have formState.isDirty, but no formState.dirtyFields?

It's a large, complex form but the isDirty state is achieved by human interaction with the form, with registration looking like this:

<input id="value" {...register("value")} defaultValue={variable.value} />

One other observation - the behavior seems to change when observed. For example, when adding this code to the form - it seems to work more as expected:

<div>
  {formState.isDirty ? "DIRTY" : "CLEAN"}
  <pre>dirty {JSON.stringify(formState.dirtyFields, null, 2)}</pre>
  <pre>touched {JSON.stringify(formState.touchedFields, null, 2)}</pre>
</div>
ConfusedNoob
  • 9,826
  • 14
  • 64
  • 85

1 Answers1

0

It seems obvious now, but the problem was I had a dependency on formState in a function called on button click. Because clicking the button doesn't cause a re-render of the form, the fresh value of formState is not retrieved from useForm - meaning it is stale.

The trick is to have this change trigger a re-render. You can do this by having it in rendered in the output (so .tsx/.jsx spots the dependency) or by using useCallback to create the save function and register formState in the dependencies of that function, a la


const save = useCallback(() => {
// save using formState dirtyFields, touchedFields etc
}, [formState]);

// ...

<button onClick={save} />


Now, it works great and this explains the behavior change when showing the dirty state in the HTML output.

ConfusedNoob
  • 9,826
  • 14
  • 64
  • 85