final-form / final-form/react-final-form

useField causes useFormState#valid to temporarily be constantly true

Open
#588 0 comments 2 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
7.4k
Forks
497
PR merge metrics
No merged PRs in 30d

Description

# the 'immediately unregister' behavior in `useField` triggers always `valid` status

### What is the current behavior?

In my form, every input does `useField` as expected. I also have a `FormError` component that displays `FORM_ERROR` and `submitError`s. It uses `useFormState()` to accomplish this as expected.

I also have a component/hook called `ValuesHandler` that allows me to easily get a callback whenever any of the values in the form changes (in my case, to sync this state to another component that wants to know the current state of the form, without coupling them further).

It looks a little something like

```jsx
/**
* ValuesHandler notifies callback function when form values change.
*/
export default function ValuesHandler({ onValues }) {
const form = useForm();
const { valid, validating, values } = useFormState({
subscription: {
valid: true,
validating: true,
values: true,
},
});

useEffect(() => {
if (!validating) {
onValues && onValues({ valid, values, form });
}
}, [form, onValues, valid, validating, values]);

return null;
}
```

Because of the mount order, what happens is:

- render a form and call `useForm`, triggering validation and then **pausing** validation
- register field A
- unregister field A, (clearing A's error and requesting record validation, but validation is paused)
- register field B
- unregister field B, (clearing B's error and requesting record validation, but validation is paused)
- call `useFormState` and immediately calculate the next form state, which has an empty errors object (since we unset every field's errors)

### What is the expected behavior?

the status of `useFieldState`'s `valid` property should not be dependent on the register/unregister calls made during component mounting. It should be

I hope my description was clear enough, not really sure how best to 'name' the bug.

### Sandbox Link

https://codesandbox.io/embed/intelligent-goodall-5kmg3

see the console for example. the `valid` property of `useFieldState` differs from that of the Form's render method, since validation is re-enabled before the second render

### What's your environment?

latest, all browsers

---

## Workaround

My workaround for now, which seems to be ok is to just add another condition to whether or not I notify my callbacks, whether or not the form is currently validating, and also use the properties from the render function instead of the actual subscriber state.

```js
import { useEffect } from 'react';
import { useForm } from 'react-final-form';

/**
* ValuesHandler notifies callback function when form values change.
*/
export default function ValuesHandler({ valid, validating, values, onValues }) {
const form = useForm();

useEffect(() => {
if (!validating && !form.isValidationPaused()) {
onValues && onValues({ valid, values });
}
}, [form, onValues, valid, validating, values]);

return null;
}

```

Contributor guide

Open the contributing guide

Research direction

Start with the linked CodeSandbox and trace the mount order involving useField, useFormState, and paused validation. Compare the subscriber's valid state with the Form render output during the first render. Done means registration and unregistration during mounting no longer make valid temporarily report true.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.