Ant Design forms
Version baseline: Ant Design 6.x (6.4.3 current stable at this review), with the current v6 documentation and React 18 or 19 compatibility; prefer React 19 for new work. Inspect the exact installed patch and migration notes before changing an existing project.
Treat the form instance as the source of truth for fields registered through Form.Item. Define the data shape first, then wire validation, submission, and server errors around that shape.
Workflow
- Define the form value type and distinguish create defaults from edit data.
- Create one
Forminstance withForm.useFormwhen the parent needs reset, validation, or programmatic updates. - Give every submitted field a stable
name; put rules on the matchingForm.Item. - Use
initialValuesfor first-render defaults. When edit data arrives later, callform.setFieldsValue; do not expectinitialValuesto react to prop changes. - Submit through
form.validateFields, set a loading state, map known server field errors withform.setFields, and keep a visible form-level error for unknown failures. - Verify invalid, valid, loading, server-error, reset, and keyboard-submit states.
type UserValues = { name: string; email: string }
const [form] = Form.useForm<UserValues>()
<Form<UserValues>
form={form}
layout="vertical"
onFinish={async (values) => saveUser(values)}
>
<Form.Item name="name" label="Name" rules={[{ required: true }]}>
<Input autoComplete="name" />
</Form.Item>
<Form.Item name="email" label="Email" rules={[{ required: true, type: "email" }]}>
<Input autoComplete="email" />
</Form.Item>
<Button htmlType="submit" type="primary">Save</Button>
</Form>
Common patterns
- Use
Form.Listfor repeatable fields and derive nested names from the provided field metadata. - Use
dependenciesorshouldUpdatefor cross-field rules, but do not combine them on the same item without a clear reason. - Normalize
Uploadvalues withvaluePropName="fileList"andgetValueFromEventonly when the field is actually managed by the form. - Use
preserve={false}for conditionally removed fields when stale values would be harmful. - Keep submit buttons disabled or loading during the request, but do not disable fields needed to explain a failure.
- Prefer
onFinishfor successful validation andonFinishFailedfor focusable error feedback.
Review traps
Look for a child with its own value and onChange fighting the form, a reset that leaves derived state behind, rules that do not match the field type, and a submit handler that sends stale props instead of validated values.