How to Validate Form in Remix: Simple Guide with Examples
In Remix, validate forms by handling input in the
action function on the server side. Use Form from Remix to submit data, then check inputs in the action and return errors to display in the UI.Syntax
In Remix, form validation happens inside the action function. You receive form data, check it, and return errors if any. The Form component handles submission and lets you show validation messages.
action: Server-side function to process and validate form data.Form: Remix component to create forms that submit to theaction.- Return an object with errors to show validation messages.
javascript
export const action = async ({ request }) => { const formData = await request.formData(); const username = formData.get('username'); const errors = {}; if (!username || username.length < 3) { errors.username = 'Username must be at least 3 characters'; } if (Object.keys(errors).length) { return errors; } // Proceed with valid data return null; };
Example
This example shows a simple username form. It validates that the username is at least 3 characters long. If invalid, it returns an error that the form displays below the input.
javascript
import { Form, useActionData } from '@remix-run/react'; export const action = async ({ request }) => { const formData = await request.formData(); const username = formData.get('username'); const errors = {}; if (!username || username.length < 3) { errors.username = 'Username must be at least 3 characters'; } if (Object.keys(errors).length) { return errors; } // Success: do something with username return null; }; export default function UsernameForm() { const errors = useActionData(); return ( <Form method="post" noValidate> <label htmlFor="username">Username:</label> <input id="username" name="username" type="text" aria-invalid={errors?.username ? true : false} aria-describedby="username-error" /> {errors?.username && ( <div id="username-error" style={{ color: 'red' }} role="alert"> {errors.username} </div> )} <button type="submit">Submit</button> </Form> ); }
Output
A form with a username input and a submit button. If username is less than 3 characters, a red error message appears below the input.
Common Pitfalls
- Not returning errors from the
actioncauses no feedback to users. - Validating only on the client side is insecure; always validate in the
action. - Forgetting to use
useActionDatato get errors and show them in the UI. - Not using
aria-invalidandaria-describedbyhurts accessibility.
javascript
/* Wrong: No error returned */ export const action = async ({ request }) => { const formData = await request.formData(); const username = formData.get('username'); if (!username || username.length < 3) { // No error returned here } return null; }; /* Right: Return errors object */ export const action = async ({ request }) => { const formData = await request.formData(); const username = formData.get('username'); const errors = {}; if (!username || username.length < 3) { errors.username = 'Username must be at least 3 characters'; } if (Object.keys(errors).length) { return errors; } return null; };
Quick Reference
Tips for validating forms in Remix:
- Always validate inside the
actionfunction on the server. - Use
Formfrom Remix for submission. - Return an errors object from
actionto show validation messages. - Use
useActionDatahook to access errors in the component. - Include accessibility attributes like
aria-invalidandaria-describedby.
Key Takeaways
Validate form data inside Remix's server-side action function for security.
Return an errors object from action to provide user feedback.
Use Remix's Form component and useActionData hook to handle form state and errors.
Add accessibility attributes to inputs for better user experience.
Always check inputs on the server, not just client-side.