---
title: Form
description: Migration guide for Form from HeroUI v2 to v3
---

<Callout type="info">
  Refer to the [v3 Form documentation](/docs/react/components/form) for complete API reference, styling guide, and advanced examples. This guide only focuses on migrating from HeroUI v2.
</Callout>

## Key Changes

### 1. Form Component Props

The Form component props remain the same between v2 and v3, with one addition:

| Prop | v2 | v3 | Notes |
|------|----|----|-------|
| `validationBehavior` | ✅ | ✅ | Same: `"native"` \| `"aria"` |
| `validationErrors` | ✅ | ✅ | Same: `Record<string, string \| string[]>` |
| `onSubmit` | ✅ | ✅ | Same |
| `onReset` | ✅ | ✅ | Same |
| `action` | ✅ | ✅ | Same |
| `method` | ✅ | ✅ | Same |
| `encType` | ✅ | ✅ | Same |
| `target` | ✅ | ✅ | Same |
| `className` | ✅ | ✅ | Same |
| `onInvalid` | ❌ | ✅ | New: Handler called when form validation fails |

## Structure Changes

In v2, Form component usage:

```tsx
import { Form, Button } from "@heroui/react";

export default function App() {
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    console.log("Form submitted");
  };

  return (
    <Form onSubmit={handleSubmit}>
      {/* Form content */}
      <Button type="submit">Submit</Button>
    </Form>
  );
}
```

In v3, Form component usage remains the same:

```tsx
import { Form, Button } from "@heroui/react";

export default function App() {
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    console.log("Form submitted");
  };

  return (
    <Form onSubmit={handleSubmit}>
      {/* Form content */}
      <Button type="submit">Submit</Button>
    </Form>
  );
}
```

## Migration Examples

### Form with Invalid Handler (New in v3)

<Tabs items={["v2", "v3"]}>
  <Tab value="v2">
    ```tsx
    {/* v2 doesn't have onInvalid prop */}
    <Form onSubmit={onSubmit}>
      {/* Form content */}
      <Button type="submit">Submit</Button>
    </Form>
    ```
  </Tab>
  <Tab value="v3">
    ```tsx
    <Form
      onInvalid={(e) => {
        e.preventDefault();
        // Custom handling when form validation fails
        console.log("Form validation failed");
      }}
      onSubmit={onSubmit}
    >
      {/* Form content */}
      <Button type="submit">Submit</Button>
    </Form>
    ```
  </Tab>
</Tabs>

The `onInvalid` handler is called when form validation fails. By default, the first invalid field will be focused. Use `e.preventDefault()` to customize this behavior.

## Summary

1. **Form Component**: No breaking changes - same props and behavior
2. **New Prop**: `onInvalid` prop available for custom validation error handling

## Migration Steps

1. **No changes required**: The Form component works the same way in v3
2. **Optional**: Use the new `onInvalid` prop if you need custom handling for validation failures

## Note on Form Fields

While the Form component itself is unchanged, form field components (like `Input`, `TextField`, etc.) have been updated in v3. Refer to their respective migration guides for details on migrating form fields within your forms.
