|
- import * as React from 'react';
- import fetchPonyfill from 'fetch-ponyfill';
- import { EncTypeSerializerMap, serializeBody, SerializerOptions } from '../../utils/serialization';
- import { ENCTYPE_MULTIPART_FORM_DATA } from '../../common';
- import { AllowedClientMethod, FormDerivedElement } from '../common';
-
- export interface UseFormFetchParams {
- clientAction?: string;
- clientHeaders?: HeadersInit;
- clientMethod: AllowedClientMethod;
- encType: string;
- invalidate?: (...args: unknown[]) => unknown;
- refresh?: (response: Response) => void;
- encTypeSerializers?: EncTypeSerializerMap;
- responseEncType: string;
- serializerOptions?: SerializerOptions;
- onSubmit?: React.FormEventHandler<FormDerivedElement>;
- }
-
- export const useFormFetch = ({
- clientAction,
- invalidate,
- clientHeaders,
- responseEncType,
- encType,
- clientMethod,
- encTypeSerializers,
- serializerOptions,
- refresh,
- onSubmit,
- }: UseFormFetchParams) => {
- const handleSubmit: React.FormEventHandler<
- FormDerivedElement
- > = React.useCallback(async (event) => {
- event.preventDefault();
- const { submitter } = event.nativeEvent as unknown as { submitter?: HTMLElement };
-
- if (clientAction) {
- invalidate?.();
- const { fetch } = fetchPonyfill();
- const headers: HeadersInit = {
- ...(clientHeaders ?? {}),
- Accept: responseEncType,
- };
- if (encType !== ENCTYPE_MULTIPART_FORM_DATA) {
- // browser automatically generates content-type header for multipart/form-data
- (headers as unknown as Record<string, string>)['Content-Type'] = encType;
- }
-
- const fetchInit: RequestInit = {
- method: clientMethod.toUpperCase(),
- headers,
- };
-
- if (!['GET', 'HEAD'].includes(clientMethod.toUpperCase())) {
- fetchInit.body = serializeBody({
- form: event.currentTarget,
- encType,
- serializers: encTypeSerializers,
- options: {
- ...serializerOptions,
- submitter,
- },
- });
- }
- const response = await fetch(clientAction, fetchInit);
- refresh?.(response);
- }
-
- onSubmit?.(event);
- }, [
- clientAction,
- invalidate,
- clientHeaders,
- responseEncType,
- encType,
- clientMethod,
- encTypeSerializers,
- serializerOptions,
- refresh,
- onSubmit,
- ]);
-
- return React.useMemo(() => ({
- handleSubmit,
- }), [
- handleSubmit,
- ]);
- };
|