• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

iusehooks / usetheform / 14553005798

19 Apr 2025 09:23PM UTC coverage: 99.185% (-0.03%) from 99.21%
14553005798

Pull #55

github

antoniopangallo
createFormStore-workspace
Pull Request #55: createFormStore-workspace

819 of 836 branches covered (97.97%)

Branch coverage included in aggregate %.

66 of 67 new or added lines in 4 files covered. (98.51%)

1736 of 1740 relevant lines covered (99.77%)

1513.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.42
/workspaces/usetheform/src/api/createFormStore.js
1
import { useState, useEffect } from "react";
2
import { DISPATCHER_LABEL } from "../utils/constants";
3
import { noop } from "../utils/noop";
4

5
export function createFormStore(initialFormState) {
6
  const { subscribe, notify } = createListener();
17✔
7
  const stateRef = {
17✔
8
    current: { state: { ...initialFormState } },
9
    formStatus: { isFormMounted: false }
10
  };
11
  const store = {
17✔
12
    mountForm(isFormMounted) {
13
      stateRef.formStatus.isFormMounted = isFormMounted;
32✔
14
    },
15
    update(formState, shouldNotify = true) {
52✔
16
      if (!stateRef.formStatus.isFormMounted) {
73✔
17
        return;
22✔
18
      }
19
      stateRef.current = { ...stateRef.current, ...formState };
51✔
20
      if (shouldNotify) {
51!
21
        notify(stateRef);
51✔
22
      }
23
    },
24
    getState() {
25
      return stateRef.current.state;
65✔
26
    }
27
  };
28
  return [store, withFieldSelector(subscribe, stateRef)];
17✔
29
}
30

31
const withFieldSelector = (subscribe, stateRef) => {
21✔
32
  return (fn, formInitialState) => {
17✔
33
    const [field, setState] = useState(() =>
87✔
34
      getValueAndSetter(stateRef, fn, formInitialState)
24✔
35
    );
36

37
    useEffect(() => {
79✔
38
      function updateState(newStateRef) {
39
        if (!newStateRef.formStatus.isFormMounted) {
60!
NEW
40
          return;
×
41
        }
42
        const valueAndSetter = getValueAndSetter(newStateRef, fn);
60✔
43
        setState(valueAndSetter);
60✔
44
      }
45

46
      const unsubscribe = subscribe(updateState);
16✔
47

48
      const valueAndSetter = getValueAndSetter(stateRef, fn, formInitialState);
16✔
49
      const [, setFn] = valueAndSetter;
16✔
50
      if (setFn !== noop) {
16✔
51
        setState(valueAndSetter);
10✔
52
      }
53

54
      return () => unsubscribe();
16✔
55
    }, []);
56

57
    return field;
79✔
58
  };
59
};
60

61
const createListener = () => {
21✔
62
  const listener = new Map();
17✔
63
  const subscribe = fn => {
17✔
64
    listener.set(fn, fn);
16✔
65
    return () => listener.delete(fn);
16✔
66
  };
67

68
  const notify = event => {
17✔
69
    listener.forEach(fn => fn(event));
60✔
70
  };
71
  return { subscribe, notify };
17✔
72
};
73

74
function getValueAndSetter(stateRef, selectorFn, formInitialState) {
75
  const { state = {}, mapFields = {} } = stateRef.current;
100!
76

77
  if (process.env.NODE_ENV !== "production") {
100!
78
    if (typeof selectorFn !== "function") {
100✔
79
      throw new Error(
4✔
80
        "createFormStore: the state selector argument must be a function"
81
      );
82
    }
83
    if (
96✔
84
      typeof formInitialState === "object" &&
102✔
85
      formInitialState.constructor === Array
86
    ) {
87
      throw new Error(
4✔
88
        "createFormStore: the initial form state argument must be an object"
89
      );
90
    }
91
  }
92

93
  const targetState =
94
    Object.keys(state).length === 0 && formInitialState
92✔
95
      ? formInitialState
96
      : state;
97

98
  let value;
99

100
  try {
92✔
101
    value = selectorFn(targetState);
92✔
102
  } catch {
103
    value = undefined;
13✔
104
  }
105

106
  let fieldDispatcher;
107
  try {
92✔
108
    fieldDispatcher = selectorFn(mapFields);
92✔
109
  } catch {
110
    fieldDispatcher = undefined;
13✔
111
  }
112

113
  const setFieldValue =
114
    fieldDispatcher?.[DISPATCHER_LABEL] || fieldDispatcher || noop;
92✔
115

116
  return [value, setFieldValue];
92✔
117
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc