Capítulo 29 de 39
useFieldArray manages a dynamic list of inputs (add/remove/reorder rows) with better performance than manually mutating a plain array in state, by returning a fields array (each entry carrying an auto-generated id/key) plus mutation methods.
useFieldArray instance must be the only one using that name.{ ...defaultValue, id } entries to .map() over; field.id (not index) must be used as the React key, otherwise reordering breaks which row's state belongs to which DOM node.setValue instead if you don't want the remount.register (required, minLength, maxLength, validate); a validation error lands at formState.errors.<name>.root.fields stays populated with every entry's disabled: true, all mutation methods become no-ops, but you still have to spread field.disabled onto each input yourself.function FieldArray() {
const { control, register } = useForm()
const { fields, append, remove } = useFieldArray({ control, name: "test" })
return (
<>
{fields.map((field, index) => (
<input key={field.id} {...register(`test.${index}.value`)} />
))}
<button type="button" onClick={() => append({ value: "" })}>append</button>
</>
)
}
field.id as key, register with an index-templated path, append supplying a full default row.| Method | Signature | Notes |
|---|---|---|
append | (obj | obj[], focusOptions?) | adds at end, focuses new row by default |
prepend | (obj | obj[], focusOptions?) | adds at start |
insert | (index, obj | obj[], focusOptions?) | adds at position |
swap | (from, to) | swap two positions |
move | (from, to) | move one entry |
update | (index, obj) | replaces one entry, remounts its row |
replace | (obj[]) | replaces the whole array |
remove | (index? | index[]) | removes one/many/all |
index as the React key instead of field.id: breaks row identity across reorders/removals.append() then remove(0) in the same click): can race against the array's own re-render; do the second mutation in a useEffect instead.shouldUnregister: true with useFieldArray: not supported — the array relies on inputs mounting/unmounting to manage its own state, so newly appended fields get unregistered on re-render and lose their values.test: ['a', 'b']): not supported — every entry must be an object (test: [{ value: 'a' }]).append/prepend/insert/update: must include real default values for every field in that row.field.id, never by array index.update remounts the row (use setValue if you need an in-place value change without remounting); replace swaps the whole array.shouldUnregister: true and flat primitive arrays are both explicitly unsupported combinations.useFieldArray to compute derived totals (e.g. cart price × quantity) from the current values.register for virtual/conditional rows inside a field array.