Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion packages/dev/s2-docs/pages/react-aria/forms.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ export async function action({request}: Route.ActionArgs) {

## Form libraries

In most cases, uncontrolled forms with the builtin validation features are sufficient. However, if you are building a truly complex form, or integrating React Aria components into an existing form, a separate form library such as [React Hook Form](https://react-hook-form.com/) or [Formik](https://formik.org/) may be helpful.
In most cases, uncontrolled forms with the builtin validation features are sufficient. However, if you are building a truly complex form, or integrating React Aria components into an existing form, a separate form library such as [React Hook Form](https://react-hook-form.com/), [Formik](https://formik.org/), or [Formisch](https://formisch.dev/) may be helpful.

### React Hook Form

Expand Down Expand Up @@ -496,3 +496,51 @@ function App() {
}
```

### Formisch

[Formisch](https://formisch.dev/) is a schema-based, headless form library for React. It validates with a [Valibot](https://valibot.dev/) schema and infers all input and output types directly from it.

Use the `Field` component from Formisch to integrate React Aria components. The render prop provides the current value, error messages, and props for the field. Instead of spreading `field.props`, pass them individually: the ref goes to `inputRef` so Formisch registers the native input element, and `field.onChange` replaces the native change handler because React Aria passes the value instead of the event. The `Form` component from Formisch wraps a native `<form>` element and calls `onSubmit` with the validated values.

```tsx
import {Field, Form, useForm} from '@formisch/react';
import * as v from 'valibot';
import {TextField} from 'vanilla-starter/TextField';
import {Button} from 'vanilla-starter/Button';

const FormSchema = v.object({
name: v.pipe(v.string(), v.nonEmpty('Name is required.'))
});

function App() {
let form = useForm({schema: FormSchema});
let onSubmit = (output) => {
// Call your API here...
};

return (
<Form of={form} onSubmit={onSubmit}>
<Field of={form} path={['name']}>
{(field) => (
<TextField
label="Name"
name={field.props.name}
inputRef={field.props.ref}
value={field.input}
// React Aria passes the value instead of the event.
onChange={field.onChange}
onFocus={field.props.onFocus}
onBlur={field.props.onBlur}
isRequired
// Let Formisch handle validation instead of the browser.
validationBehavior="aria"
isInvalid={field.errors !== null}
errorMessage={field.errors?.[0]} />
)}
</Field>
<Button type="submit">Submit</Button>
</Form>
);
}
```