# FieldArray

> React Hook Form's FieldArray component wraps useFieldArray in a render prop, so you can append, remove, and manage dynamic form fields declaratively.

Source: https://react-hook-form.com/docs/usefieldarray/fieldarray

## `FieldArray:` [FieldArrayProps](https://react-hook-form.com/ts#FieldArrayProps) _(since v7.81.0)_

Component based on the [`useFieldArray`](https://react-hook-form.com/docs/usefieldarray) hook, useful for working with dynamic field arrays as a headless/controlled component. All props are the same as `useFieldArray`, plus a `render` prop that receives the hook's return value.

```javascript
<FieldArray
  control={control}
  name="test"
  render={({ fields }) =>
    fields.map((field, index) => (
      <input key={field.id} {...register(`test.${index}.value`)} />
    ))
  }
/>
```

### Props

---

| Name               | Type                               | Required | Description                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ---------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `render`           | `Function`      | ✓        | Render prop function that receives the same object [`useFieldArray`](https://react-hook-form.com/docs/usefieldarray#return) returns (`fields`, `append`, `prepend`, `insert`, `remove`, `swap`, `move`, `update`, `replace`) and returns a React element.                                                                                                                                                                                                    |
| `name`             | `string`        | ✓        | Name of the field array. **Note:** Dynamic names are not supported.                                                                                                                                                                                                                                                                                                                                                               |
| `control`          | `Object`        |          | [`control`](https://react-hook-form.com/docs/useform/control) object provided by `useForm`. It's optional if you are using `FormProvider`.                                                                                                                                                                                                                                                                                                                   |
| `shouldUnregister` | `boolean`       |          | Whether Field Array will be unregistered after unmount.                                                                                                                                                                                                                                                                                                                                                                           |
| `disabled`         | `boolean`       |          | Disables the entire field array. When `true`, `fields` remains populated but every entry's `disabled` property is set to `true`, all mutation methods (`append`, `prepend`, `insert`, `remove`, `swap`, `move`, `update`, `replace`) become no-ops, and the array's internal subscriptions are not set up. Useful for conditionally enabling a field array in discriminated union form shapes.                                    |
| `keyName`          | `string = "id"` |          | Name of the attribute with autogenerated identifier to use as the `key` prop. This prop is no longer required and is removed in v8, where rows always use `key` (see [v8 migration notes](https://react-hook-form.com/migrate-v7-to-v8#useFieldArray)).                                                                                                                                                                                                      |
| `rules`            | `Object`        |          | The same validation `rules` API as for [`register`](https://react-hook-form.com/docs/useform/register), which includes: `required`, `minLength`, `maxLength`, `validate`. In case of validation error, the `root` property is appended to `formState.errors?.<name>?.root` (e.g. `formState.errors?.test?.root` for a field array named `test`), of type [`FieldError`](https://react-hook-form.com/ts/#FieldError). **Important:** This is only applicable to **built-in** validation. |

### Return

---

The following table contains information about the object passed to the `render` prop function — it's identical to what [`useFieldArray`](https://react-hook-form.com/docs/usefieldarray#return) returns.

| Name      | Type                                                                                  | Description                                                                                                                                                                                                                                                                        |
| --------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fields`  | `object & \{ id: string \}`                                        | This `object` contains the `defaultValue` and `id` for your component. When the hook-level `disabled` prop is set, every entry's `disabled` property reflects it — but this is not automatically forwarded to the registered input; you need to spread it onto the input yourself. |
| `append`  | `(obj: object \| object[], focusOptions) => void`                  | Append input/inputs to the end of your fields and focus. The input value will be registered during this action. **Important:** append data is required and not partial.                                                                                                            |
| `prepend` | `(obj: object \| object[], focusOptions) => void`                  | Prepend input/inputs to the start of your fields and focus. The input value will be registered during this action. **Important:** prepend data is required and not partial.                                                                                                        |
| `insert`  | `(index: number, value: object \| object[], focusOptions) => void` | Insert input/inputs at particular position and focus. **Important:** insert data is required and not partial.                                                                                                                                                                      |
| `swap`    | `(from: number, to: number) => void`                               | Swap input/inputs position.                                                                                                                                                                                                                                                        |
| `move`    | `(from: number, to: number) => void`                               | Move input/inputs to another position.                                                                                                                                                                                                                                             |
| `update`  | `(index: number, obj: object) => void`                             | Update input/inputs at a particular position, updated fields will get unmounted and remounted. If this is not desired behavior, please use [`setValue`](https://react-hook-form.com/docs/useform/setvalue) API instead. **Important:** update data is required and not partial.                               |
| `replace` | `(obj: object[]) => void`                                          | Replace the entire field array values.                                                                                                                                                                                                                                             |
| `remove`  | `(index?: number \| number[]) => void`                             | Remove input/inputs at particular position, or remove all when no index provided.                                                                                                                                                                                                  |

> **Important: Rules**
>
> - The same rules that apply to [`useFieldArray`](https://react-hook-form.com/docs/usefieldarray#rules) apply here — `field.id` (not `index`) must be used as the component `key`, and `shouldUnregister: true` is not supported. In v8, use `field.key` instead of `field.id`.
> - `render` is called on every render, so keep it free of side effects.
>

### Examples

---

```tsx
import { useForm, FieldArray } from "react-hook-form"

type FormValues = {
  test: { value: string }[]
}

export default function App() {
  const { control, register, handleSubmit } = useForm<FormValues>({
    defaultValues: {
      test: [{ value: "" }],
    },
  })

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <FieldArray
        control={control}
        name="test"
        render={({ fields, append, remove }) => (
          <>
            {fields.map((field, index) => (
              <div key={field.id}>
                <input {...register(`test.${index}.value`)} />
                <button type="button" onClick={() => remove(index)}>
                  Delete
                </button>
              </div>
            ))}
            <button type="button" onClick={() => append({ value: "" })}>
              Append
            </button>
          </>
        )}
      />
      <input type="submit" />
    </form>
  )
}
```

### Tips

---

- Use `FieldArray` when you cannot call a hook, for example when a field array is rendered conditionally or inside a loop. Hooks cannot be called conditionally, but components can be rendered conditionally.
- For nested arrays, render a `FieldArray` inside another one's `render`, and build the name from the parent index:

  ```javascript
  <FieldArray
    control={control}
    name="sections"
    render={({ fields }) =>
      fields.map((section, index) => (
        <FieldArray
          key={section.id}
          control={control}
          name={`sections.${index}.questions`}
          render={({ fields: questions, append }) => (
            <Questions fields={questions} append={append} />
          )}
        />
      ))
    }
  />
  ```

- Errors from `rules` are stored at `errors.<name>.root`, for example `errors.sections?.root?.message`. Show them next to the list, not next to one row.
