Multiple forms and actions on a page with Remix
Remix uses a file-based approach to routing, so each file in your /routes
folder corresponds to a particular URL.
A page's loader function can be treated like a handler for all GET
and HEAD
requests to that endpoint, while a page's action function can be treated like a handler for all other requests (POST
, PUT
, PATCH
, DELETE
, etc…)
Since all forms on a page will submit to the same action, there's no built-in way of determining which form was submitted.
Multiple forms on a page
To work around this, you can add a hidden input with a name
and value
to your submit button. The name
will be the same for all forms on the page, and the value
will be unique to that form.
<input type="hidden" name="intent" value="LIKE" />
Multiple actions from a single form
When you submit a form, the browser will include all of its form elements, including hidden inputs, in the request body.
One exception to this rule is the submit buttons themselves. The only submit button that will be included in the request body is the one that was clicked.
So if you want to submit multiple actions from a single form, you can add name="intent"
to the submit button
<form method="post"> <input type="hidden" name="tweetId" value="asdfasdfasdfasdf" /> <button type="submit" name="intent" value="LIKE"> Like </button> <button type="submit" name="intent" value="RETWEET"> Retweet </button> <button type="submit" name="intent" value="REPLY"> Reply </button> <button type="submit" name="intent" value="SHARE"> Share </button></form>
Determining which action to take
In your action, you can use the value of the intent
input to determine which action to take.
export async function action({ request,}: ActionFunctionArgs) { const formData = await request.formData() const intent = formData.get("intent") if (intent === "LIKE") { return likeTweetAction(args) } if (intent === "RETWEET") { return retweetAction(args) } if (intent === "REPLY") { return replyAction(args) } if (intent === "SHARE") { return shareAction(args) } throw new Error("Unknown action")}
For type safety, you can use zod to validate the inputs for each action