Will King
Design Pattern
Remix

You should be wrapping Remix’s Form component with your own

Welp, now that I got you here with the clickbait…

You know what is annoying when building an app? Making sure all of your forms have the default fields that you need like your CSRF token, referrer, or a redirectTo field.

Here is how I handle that. Comments on the FormProps type explain the extra fields use cases.

// ~/components/kits/Form

import type { FormProps as RFormProps } from "@remix-run/react"

import { Form as RForm } from "@remix-run/react"

export type FormProps = RFormProps & {
/**
* Allows the passing of a fetcher.Form
* @default RForm
*/
as?: typeof RForm
/*
* Used on routes with multiple actions to identify the submitted form.
* @default undefined
*/
actionId?: string
/*
* Tells the action where to send a successful response
* @default undefined
*/
redirectTo?: string
}

export default function Form({
	children,
	as,
	actionId,
	redirectTo,
    method = "post",
    ...props
}: FormProps) {
	const { pathname } = useLocation()
	const { csrf } = useRootLoaderData()
	const _Form = as || RForm
	return (
		<_Form
          {...props}
          method={method === "get" ? "get" : "post"}
        >
			<input type="hidden" name="_referrer" value={pathname} />
			<input type="hidden" name="_csrf" value={csrf} />
            <input type="hidden" name="_method" value={method} />
			{actionId ? <input type="hidden" name="action" value={actionId} /> : null}
			{redirectTo ? (
				<input type="hidden" name="redirectTo" value={redirectTo} />
			) : null}
			{children}
		</_Form>
	)
}

Updates and More

Get updated when new articles, products, or components are released. Also, whatever else I feel like would be fun to send out.