Created
April 7, 2024 19:21
-
-
Save JTRNS/63e56fa398b17bc7519c422caa510dbe to your computer and use it in GitHub Desktop.
Remix Form Actions Helper
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 type { ActionFunctionArgs, ActionFunction } from "@remix-run/node"; | |
import type { AnyZodObject, z } from "zod" | |
export type FormActionHandler<T extends AnyZodObject> = (data: z.infer<T>, args: ActionFunctionArgs) => Promise<Response | null> | |
export type FormAction<T extends AnyZodObject> = { | |
schema: T | |
} & { | |
handler: FormActionHandler<T> | |
} | |
export function createFormActions<T extends AnyZodObject>(actions: Record<string, FormAction<T>>): ActionFunction { | |
async function handleFormActions(args: ActionFunctionArgs) { | |
const req = args.request.clone(); | |
// check the method is post otherwise throw 405 | |
if (req.method !== "POST") { | |
throw new Response("Method Not Allowed", { status: 405 }); | |
} | |
const contentType = req.headers.get("Content-Type"); | |
if (!contentType || contentType.toLowerCase() !== "application/x-www-form-urlencoded") { | |
throw new Response("Unsupported Media Type", { status: 415 }); | |
} | |
const formdata = await req.formData(); | |
// ensure that formdata has an "_action" property and that its value is a key in actions object | |
const actionKey = formdata.get("_action")?.toString(); | |
if (!actionKey || !actions[actionKey]) { | |
throw new Response("Bad Request", { status: 400 }); | |
} | |
const action = actions[actionKey]; | |
// remove "_action" from formdata | |
formdata.delete("_action"); | |
const data = action.schema.parse(Object.fromEntries(formdata)); | |
return action.handler(data, args) | |
} | |
return handleFormActions; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment