useForm.ts 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import { ApiResulState, FetchApiInterface } from "./../utils/api";
  2. import { FormEventHandler, useState } from "react";
  3. export type FormMessage = {
  4. message: string;
  5. };
  6. export type Success = FormMessage & {
  7. result: User;
  8. };
  9. type SubmitHandler = FormEventHandler<HTMLFormElement>;
  10. type UseForm = {
  11. loading: boolean;
  12. submitHandler: SubmitHandler;
  13. error?: FormMessage;
  14. success?: Success;
  15. };
  16. const useForm = <T>(
  17. fetchApi: FetchApiInterface<T>,
  18. resetAfterSubmit?: boolean
  19. ): UseForm => {
  20. const [error, setError] = useState<FormMessage>();
  21. const [loading, setLoading] = useState(false);
  22. const [success, setSuccess] = useState<Success>();
  23. const submitHandler: FormEventHandler<HTMLFormElement> = async (event) => {
  24. event.preventDefault();
  25. setLoading(true);
  26. const formData = new FormData(event.currentTarget);
  27. const body = Object.fromEntries(formData.entries()) as unknown as T;
  28. const result = await fetchApi(body);
  29. setLoading(false);
  30. switch (result.state) {
  31. case ApiResulState.SUCCESS: {
  32. setSuccess({ message: result.message, result: result.user });
  33. setError(undefined);
  34. if (resetAfterSubmit) {
  35. (event.target as HTMLFormElement).reset();
  36. }
  37. break;
  38. }
  39. case ApiResulState.ERROR: {
  40. setError({ message: result.error });
  41. setSuccess(undefined);
  42. break;
  43. }
  44. }
  45. };
  46. return { error, loading, success, submitHandler };
  47. };
  48. export default useForm;