aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils/hooks/use-form/use-form-values/use-form-values.ts
blob: 8a0962f710032a6a90769821e88c8d7753902e2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import {
  type ChangeEventHandler,
  useCallback,
  useState,
  type ChangeEvent,
} from 'react';

const isBooleanField = (
  target: EventTarget & (HTMLInputElement | HTMLTextAreaElement)
): target is EventTarget & HTMLInputElement =>
  target.type === 'checkbox' || target.type === 'radio';

export type UseFormValuesReturn<T extends Record<string, unknown>> = {
  /**
   * A method to reset the fields to their initial values.
   *
   * @returns {void}
   */
  reset: () => void;
  /**
   * A method to handle input or textarea update.
   *
   * @param {ChangeEvent<HTMLTextAreaElement | HTMLInputElement>} e - The event.
   * @returns {void}
   */
  update: (e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => void;
  /**
   * The fields values.
   */
  values: T;
};

/**
 * React hook to handle form values update and reset.
 *
 * @template {object} T - The object keys should match the fields name.
 * @param {T} initialValues - The fields initial values.
 * @returns {UseFormValuesReturn<T>} An object with values and two methods.
 */
export const useFormValues = <T extends Record<string, unknown>>(
  initialValues: T
): UseFormValuesReturn<T> => {
  const [values, setValues] = useState(initialValues);

  /**
   * Reset the field to their initial values.
   */
  const reset = useCallback(() => {
    setValues(initialValues);
  }, [initialValues]);

  /**
   * Handle input and textarea update.
   *
   * @param {ChangeEvent<HTMLTextAreaElement | HTMLInputElement>} e - The event.
   * @returns {void}
   */
  const update: ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement> =
    useCallback(({ target }) => {
      setValues((prevData) => {
        return {
          ...prevData,
          [target.name]: isBooleanField(target) ? target.checked : target.value,
        };
      });
    }, []);

  return { values, reset, update };
};