|
| 1 | +# Form System Essential Knowledge |
| 2 | + |
| 3 | +## ID Generation and Field Connection |
| 4 | + |
| 5 | +### useFieldProps Behavior |
| 6 | + |
| 7 | +`useFieldProps` handles ID generation and label-input connection automatically. It has **two distinct modes**: |
| 8 | + |
| 9 | +#### 1. Form-Connected Fields (with `name` prop) |
| 10 | +- Calls `useField` for full form integration |
| 11 | +- Generates unique IDs using the `createId` mechanism based on field name |
| 12 | +- Manages form state, validation, onChange/onBlur handlers |
| 13 | +- Example: `<TextInput name="email" />` inside a `<Form>` |
| 14 | + |
| 15 | +#### 2. Standalone Fields (no `name` prop) |
| 16 | +- **Does NOT call `useField`** to avoid interference with controlled component behavior |
| 17 | +- Uses React's `useId()` to generate IDs directly |
| 18 | +- Preserves original props including `value` and `onChange` handlers |
| 19 | +- Example: `<RadioGroup value={state} onChange={setState} />` without `name` |
| 20 | + |
| 21 | +### Critical Rule: Don't Call useField for Standalone Fields |
| 22 | + |
| 23 | +**Why**: Calling `useField` for standalone fields creates state management and side effects that interfere with controlled component behavior. This breaks components like RadioGroup in controlled mode. |
| 24 | + |
| 25 | +### Label-Input Connection |
| 26 | + |
| 27 | +`useFieldProps` automatically sets `labelProps.for` to match the field's ID when an ID exists. This ensures proper accessibility and label clicking behavior. |
| 28 | + |
| 29 | +**Components should NOT manually set**: |
| 30 | +- `labelProps.for` |
| 31 | +- Generate their own IDs using `useId()` |
| 32 | + |
| 33 | +This is handled centrally by `useFieldProps`. |
| 34 | + |
| 35 | +## Field Component Pattern |
| 36 | + |
| 37 | +```tsx |
| 38 | +function MyField(props) { |
| 39 | + props = useProviderProps(props); |
| 40 | + props = useFormProps(props); |
| 41 | + props = useFieldProps(props, { defaultValidationTrigger: 'onBlur' }); |
| 42 | + |
| 43 | + // Now props.id is set (if needed) and props.labelProps.for matches it |
| 44 | + // Just use props.id directly, don't generate your own |
| 45 | + |
| 46 | + return <input id={props.id} {...otherProps} />; |
| 47 | +} |
| 48 | +``` |
| 49 | + |
| 50 | +## ID Generation Examples |
| 51 | + |
| 52 | +- Form field: `username` → `username`, `username_1`, `username_2` (incremental) |
| 53 | +- Standalone: `undefined` → `react-aria-123` (React's useId format) |
| 54 | +- Explicit ID: Always preserved as-is |
| 55 | + |
0 commit comments