useForm
A drop-in useForm replacement with Standard Schema validation and type-safe fields.
Overview
useForm is a drop-in replacement for Ant Design's Form.useForm() hook that adds Standard Schema validation support. This means you can use any schema library that implements the Standard Schema spec, such as Zod, Valibot, ArkType, and more.
Key Features
- Schema-driven validation - Define your form schema once and get automatic field-level validation
- Type inference - Form values are automatically typed based on your schema's output type
- Automatic required field detection - Fields are marked as required based on schema validation
- Typed FormItem & FormList - Get autocomplete and type checking for field names
- Seamless Ant Design integration - Works with all existing Ant Design Form features
Usage
import React from "react";
import { , , } from "antd";
import { } from "zod"; // Or Valibot, ArkType, etc.
import { } from "@dyrhoi/antd-forge";
const = .({
: .().(3, "Username must be at least 3 characters"),
});
function () {
const { , } = ({
: ,
: (values) => { // `values` have been validated and are type-safe
},
});
return (
< {...} ="vertical">
< name={["username"]} ="Username"> < />
</>
< ="primary" ="submit">
Submit
</>
</>
);
}Auto Submit
The autoSubmit option enables automatic form submission without requiring a submit button. This is useful for search forms, filters, and live previews. See the Auto Submit example for a live demo.
How It Works
Auto submit uses a leading + trailing debounce pattern:
- Leading edge: Submits immediately on the first change (instant feedback for Select, Radio, etc.)
- Trailing edge: Submits again after the debounce period if values changed (catches rapid typing)
This gives you the best of both worlds—instant response for discrete controls like dropdowns and radio buttons, while still debouncing rapid text input.
Modes
| Mode | Description |
|---|---|
'off' | (Default) No automatic submission. Form submits only on explicit submit action. |
'auto' | Automatically submits when any field value changes using leading + trailing debounce. |
Basic Usage
const { formProps, FormItem } = useForm({
validator: schema,
autoSubmit: "auto",
onFinish: (values) => {
// Called immediately on first change, then debounced for rapid changes
},
});Custom Debounce
By default, auto mode uses a 300ms debounce for the trailing edge. You can customize this:
const { formProps, FormItem } = useForm({
validator: schema,
autoSubmit: { mode: "auto", debounce: 500 }, // 500ms debounce
onFinish: (values) => {
// Leading edge: fires immediately
// Trailing edge: fires 500ms after user stops changing values
},
});Dynamic Fields (FormList)
useForm provides a typed FormList component for managing dynamic arrays of fields. See the FormList example for a live demo.
const { formProps, FormList } = useForm({
validator: schema,
onFinish: (values) => console.log(values),
});
return (
<Form {...formProps}>
<FormList name={["items"]}>
{(fields, { add, remove }, { errors }) => (
<>
{fields.map((field) => (
<Form.Item key={field.key} {...field}>
<Input />
</Form.Item>
))}
<Button onClick={() => add()}>Add Item</Button>
</>
)}
</FormList>
</Form>
);