Remix Validated Form

v6 is coming!

Check out the RFC to get an early look or leave a comment.

Type declaration
function useFieldArray<Item>(
  name: string,
  options?: UseFieldArrayOptions
): [
  items: FieldArrayItem<Item>[],
  helpers: FieldArrayHelpers<Item>,
  error: string | undefined,
type UseFieldArrayOptions = {
  formId?: string;
  validationBehavior?: Partial<
type FieldArrayItem<Item> = {
  defaultValue: Item,
  key: string;
type FieldArrayHelpers<Item> = {
  push: (item: Item) => void;
  swap: (indexA: number, indexB: number) => void;
  move: (from: number, to: number) => void;
  insert: (index: number, value: Item) => void;
  unshift: (value: Item) => void;
  remove: (index: number) => void;
  pop: () => void;
  replace: (index: number, value: Item) => void;

A hook that makes it easy to work with dynamic arrays of values. It returns:




The name of the "field". If you're using array syntax, then this is the base name of the field (not include array index specifier).

Example: If you're items named todos[0], todos[1], etc, then the name would be todos.


Allows you to use the hook outside a form.

{ initial: "onChange" | "onSubmit"; whenSubmitted: "onChange" | "onSubmit"; }

Allows you to configure when the field should validate. The keys (initial, whenSubmitted) are states the field/form could be in, and the values (onChange, onSubmit) are when you want to validate while in that state.


Each item in the array has the following properties:


The default value for the item. When an item was created by a helper like push, this is the value that was passed to the helper.


This value does not change after the item is created. If you want to access the current value of the item, you'll need to integrate with useControlField same as regular fields.


An auto-generated key that you can use as the key prop when rendering the list of items. This key is local to this particular call to useFieldArray, so calling useFieldArray multiple times for the same field will result in different keys.


Many of these helpers parallel native array helpers, but please note that, unlike the native array methods, none of these helpers return anything.

(item: Item) => void

Adds a new item to the end of the array.

(indexA: number, indexB: number) => void

Swaps the items at the given indices.

(from: number, to: number) => void

Moves the item at the from index to the to index.

(index: number, item: Item) => void

Inserts an item at the given index.

() => void

Removes the item at the start of the array.

() => void

Removes the item at the end of the array.

(index: number) => void

Removes the item at the given index.

(index: number, item: Item) => void

Replaces the item at the given index.