MCPcopy
hub / github.com/final-form/react-final-form / useFormState

Function useFormState

src/useFormState.ts:9–73  ·  view source on GitHub ↗
({
  onChange,
  subscription = all,
}: UseFormStateParams<FormValues> = {})

Source from the content-addressed store, hash-verified

7import shallowEqual from "./shallowEqual";
8
9function useFormState<FormValues = Record<string, any>>({
10 onChange,
11 subscription = all,
12}: UseFormStateParams<FormValues> = {}): FormState<FormValues> {
13 const form: FormApi<FormValues> = useForm<FormValues>("useFormState");
14 const onChangeRef = React.useRef(onChange);
15 onChangeRef.current = onChange;
16
17 // Initialize with current form state WITHOUT triggering callbacks during render.
18 // We intentionally use getState() here so render-prop consumers (e.g. <FormSpy>{...})
19 // can read a fully-populated initial state on first render.
20 const [state, setState] = React.useState<FormState<FormValues>>(() =>
21 form.getState(),
22 );
23
24 // We want `onChange` to be called AFTER render (fixes #809) and only with the
25 // subscription-filtered state.
26 const firstSubscriptionRef = React.useRef(true);
27 const pendingOnChangeRef = React.useRef<FormState<FormValues> | null>(null);
28 const lastOnChangeRef = React.useRef<FormState<FormValues> | null>(null);
29
30 React.useEffect(() => {
31 const unsubscribe = form.subscribe((newState) => {
32 // Ensure we set state at least once from the subscription, even if equal,
33 // so that `onChange` can be fired from an effect after the first render.
34 const isFirst = firstSubscriptionRef.current;
35 if (isFirst) {
36 firstSubscriptionRef.current = false;
37 }
38
39 pendingOnChangeRef.current = newState;
40
41 setState((prevState) => {
42 if (isFirst || !shallowEqual(newState, prevState)) {
43 return newState;
44 }
45 return prevState;
46 });
47 }, subscription);
48
49 return unsubscribe;
50 // eslint-disable-next-line react-hooks/exhaustive-deps
51 }, []);
52
53 React.useEffect(() => {
54 const pending = pendingOnChangeRef.current;
55 if (!pending || !onChangeRef.current) {
56 return;
57 }
58
59 // Only fire when the subscription has produced a new state and it differs
60 // from what we've already emitted.
61 if (lastOnChangeRef.current === null || !shallowEqual(pending, lastOnChangeRef.current)) {
62 onChangeRef.current(pending);
63 lastOnChangeRef.current = pending;
64 }
65
66 // Clear pending once we've handled it.

Callers 6

Comp1Function · 0.85
MyComponentFunction · 0.85
MyTypedComponentFunction · 0.85
FormSpyFunction · 0.85
MyFormStateComponentFunction · 0.85
TestFunction · 0.85

Calls 3

addLazyFormStateFunction · 0.90
useFormFunction · 0.85
shallowEqualFunction · 0.85

Tested by 5

Comp1Function · 0.68
MyComponentFunction · 0.68
MyTypedComponentFunction · 0.68
MyFormStateComponentFunction · 0.68
TestFunction · 0.68

Used in the wild real call sites across dependent graphs

searching dependent graphs…