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>
)
}