Skip to content

Instantly share code, notes, and snippets.

@sergiodxa
Created January 10, 2021 01:21
Show Gist options
  • Save sergiodxa/9835e64ef4e551d83f5e27d944c43714 to your computer and use it in GitHub Desktop.
Save sergiodxa/9835e64ef4e551d83f5e27d944c43714 to your computer and use it in GitHub Desktop.
A Form component which automatically run a React Query v2 mutation
import { useCallback, ReactNode, FormEventHandler } from "react";
import { MutationResultPair, MutateConfig, QueryStatus } from "react-query";
import * as yup from "yup";
function noop() {}
type FormProps<Data> = {
action: MutationResultPair<Data, Error, FormData, never | (() => void)>;
children(status: QueryStatus): ReactNode;
validation: yup.ObjectSchema;
onInvalid?(error: yup.ValidationError): void;
} & Omit<MutateConfig<Data, Error, FormData, () => void>, "onMutate">;
export function Form<Data>({
children,
action: [action, { status }],
validation,
onSuccess = noop,
onError = noop,
onSettled = noop,
onInvalid = noop,
}: FormProps<Data>) {
// callbacks
const handleSubmit = useCallback<FormEventHandler<HTMLFormElement>>(
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
validation
// @ts-expect-error
.validate(Object.fromEntries(formData.entries()))
.then(() => {
action(formData, {
onSuccess,
onError,
onSettled,
});
})
.catch((error: yup.ValidationError) => onInvalid(error));
},
[action, onError, onInvalid, onSettled, onSuccess, validation],
);
// render
return (
<form onSubmit={handleSubmit} style={{ display: "contents" }}>
{children(status)}
</form>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment