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

Bug: useFormState implementation may swallow state updates

Open
#784 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
JavaScript
Stars
7.4k
Forks
497
PR merge metrics
No merged PRs in 30d

Description

### Are you submitting a **bug report** or a **feature request**?

bug report

### What is the current behavior?

Current implementation of `useFormState` hook is not reliable. State initialization and `useEffect` hook are called asynchronously:

https://github.com/final-form/react-final-form/blob/abd6d6266d2f6953a1995cb3dedd26f198e653fc/src/useFormState.js#L19-L46

This means, that between this two calls, the form state may be changed. And yes, it happens sometimes :(

### What is the expected behavior?

When you using `useFormState` hook it should replicate **all** calls of `form.subscribe()`'s callback!

I think, that `firstRender.current` is a bad way for skipping needless state updates. Because this may cause skipping of really important updates from subscription. Instead I suggest the following implementation:

```js
function useFormState({
onChange,
subscription = all,
}: UseFormStateParams = {}): FormState {
const form: FormApi = useForm('useFormState');
const unsubscribe = React.useRef(() => {});

// synchronously register and unregister to query field state for our subscription on first render
const [state, setState] = React.useState>(
(): FormState => {
let initialState: FormState;
let initialRender = true;

unsubscribe.current = form.subscribe((state) => {
if (initialRender) {
initialState = state;
initialRender = false;
} else {
setState(state);
}

if (onChange) {
onChange(state);
}
}, subscription);

return initialState;
},
);

React.useEffect(
() => unsubscribe.current,
// eslint-disable-next-line react-hooks/exhaustive-deps
[],
);

return state;
}
```

### Sandbox Link

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.