Created
June 16, 2021 14:02
-
-
Save arnonate/731b946dc157ff06ee4180705335da44 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useState, FormEvent } from 'react'; | |
type FormField = { | |
field: string; | |
errorMessage?: string; | |
hasError?: boolean; | |
required?: boolean; | |
value?: boolean | string | string[] | null; | |
}; | |
export type FormFields = { | |
[key: string]: FormField; | |
}; | |
export type UseForm = { | |
formState: FormFields; | |
getSubmitterShouldValidate: (event: FormEvent) => boolean; | |
getData: <T>() => T | null; | |
setData: (field: string, value: FormField['value']) => void; | |
getErrors: () => FormField[]; | |
setErrors: (field: string, value: boolean) => void; | |
setRequired: (field: string, required: boolean) => void; | |
isDirty: boolean; | |
cleanForm: () => void; | |
}; | |
const useForm = (initialState: Readonly<FormFields>): UseForm => { | |
const [cleanState, setCleanState] = useState<FormFields>({ ...initialState }); | |
const [formState, setFormState] = useState<FormFields>({ ...initialState }); | |
const [isDirty, setIsDirty] = useState<boolean>(false); | |
const getSubmitterShouldValidate = (event: FormEvent): boolean => { | |
const nativeEvent = (event.nativeEvent as unknown) as { | |
submitter: { formNoValidate: boolean }; | |
}; | |
return !nativeEvent.submitter.formNoValidate; | |
}; | |
const getData = <T,>(): T | null => { | |
const postData = Object.values(formState); | |
const postBody = {}; | |
if (postData.length < 1) { | |
return null; | |
} | |
return postData.reduce( | |
(obj, item) => ({ | |
...obj, | |
[item.field]: item.value, | |
}), | |
postBody, | |
) as T; | |
}; | |
const setData: UseForm['setData'] = (field, value) => { | |
setFormState((data) => ({ | |
...data, | |
[field]: { | |
...data[field], | |
value, | |
hasError: false, | |
}, | |
})); | |
}; | |
const getErrors: UseForm['getErrors'] = () => { | |
const fields = Object.values(formState); | |
return fields.filter((field) => field.required && !field.value); | |
}; | |
const setErrors: UseForm['setErrors'] = (field, value) => { | |
setFormState((data) => ({ | |
...data, | |
[field]: { | |
...data[field], | |
hasError: value, | |
}, | |
})); | |
}; | |
const setRequired: UseForm['setRequired'] = (field, required) => { | |
setFormState((data) => ({ | |
...data, | |
[field]: { | |
...data[field], | |
required, | |
}, | |
})); | |
}; | |
const cleanForm: UseForm['cleanForm'] = () => { | |
setCleanState({ ...formState }); | |
}; | |
useEffect(() => { | |
if ( | |
JSON.stringify(Object.values(cleanState).map((item) => item.value)) === | |
JSON.stringify(Object.values(formState).map((item) => item.value)) | |
) { | |
setIsDirty(false); | |
} else { | |
setIsDirty(true); | |
} | |
}, [cleanState, formState]); | |
return { | |
formState, | |
getSubmitterShouldValidate, | |
getData, | |
setData, | |
getErrors, | |
setErrors, | |
setRequired, | |
isDirty, | |
cleanForm, | |
}; | |
}; | |
export default useForm; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment