-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathuseFormState.ts
46 lines (38 loc) · 1.41 KB
/
useFormState.ts
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
import { isEqual } from "lodash";
import { useCallback, useMemo, useRef, useState } from "react";
export type FormState<T> = {
values: T;
updateFormValues: (newState: Partial<T>) => void;
setInitialValues: (newState: T) => void;
resetForm: () => void;
isDirty: boolean;
};
export function useFormState<Values extends Record<string, unknown>>(
initialValues: Values
): FormState<Values> {
const memoizedInitialValues = useRef(initialValues);
// this could be replaced with some form library later
const [values, setValues] = useState<Values>(memoizedInitialValues.current);
const setInitialValues = useCallback((newInitialValues: Values) => {
memoizedInitialValues.current = newInitialValues;
setValues(newInitialValues);
}, []);
const updateFormValues = useCallback((newState: Partial<Values>) => {
setValues((prevState: Values) => {
if (isEqual(newState, prevState)) return prevState;
return { ...prevState, ...newState };
});
}, []);
const resetForm = useCallback(() => {
setValues(memoizedInitialValues.current);
}, [memoizedInitialValues]);
const isDirty = useMemo(
() => !isEqual(values, memoizedInitialValues.current),
[values, memoizedInitialValues],
);
const formState = useMemo(
() => ({ values, updateFormValues, resetForm, isDirty, setInitialValues }),
[values, updateFormValues, resetForm, isDirty, setInitialValues],
);
return formState
}