How to Handle Multiple Forms in Remix: Fix and Best Practices
Remix, to handle multiple forms on the same page, assign each form a unique name or action attribute and check request.formData() in the action function to identify which form was submitted. This lets you run different logic for each form within a single action handler.Why This Happens
When you have multiple forms on one Remix page but use a single action function without distinguishing which form was submitted, Remix treats all form submissions the same. This causes your server code to run the same logic regardless of the form, leading to unexpected behavior or errors.
export const action = async ({ request }) => { const formData = await request.formData(); // No check for which form submitted const data = formData.get('input'); // Process data assuming only one form return { message: `Received: ${data}` }; }; export default function Page() { return ( <> <form method="post"> <input name="input" /> <button type="submit">Submit Form 1</button> </form> <form method="post"> <input name="input" /> <button type="submit">Submit Form 2</button> </form> </> ); }
The Fix
Give each form a unique name or action attribute or include a hidden input to identify the form. Then, in the action function, check this identifier to run the correct logic for each form.
export const action = async ({ request }) => { const formData = await request.formData(); const formName = formData.get('formName'); if (formName === 'form1') { const data = formData.get('input1'); return { message: `Form 1 received: ${data}` }; } if (formName === 'form2') { const data = formData.get('input2'); return { message: `Form 2 received: ${data}` }; } return { message: 'Unknown form submitted' }; }; export default function Page() { return ( <> <form method="post"> <input name="input1" /> <input type="hidden" name="formName" value="form1" /> <button type="submit">Submit Form 1</button> </form> <form method="post"> <input name="input2" /> <input type="hidden" name="formName" value="form2" /> <button type="submit">Submit Form 2</button> </form> </> ); }
Prevention
Always include a hidden input or unique identifier in each form to distinguish them in your action handler. Use clear naming conventions for inputs and form identifiers. Test each form separately to ensure the correct logic runs. Consider splitting complex forms into separate routes if needed for clarity.
Related Errors
1. Missing form identifier: Causes all forms to trigger the same logic, leading to bugs.
2. Duplicate input names: Can cause unexpected data overwrites in formData.
3. Forgetting method="post": Forms default to GET, which Remix action does not handle.