Craig Glennie

Using react-hook-form useFieldArray with useForm and defaultValues

Another item in my “react-hook-forms is confusing” list. Not sure how many items I need before I switch perspective from “I just don’t grok react-hook-forms yet” to “it’s not me, it’s you”.

Anyway, I was trying to use useFieldArray to create a dynamic form. I was also using useForm to see some default values, which is standard practice AFAIK.

const data = {
  timezone: "New Zealand",
  emails: ["craig@example.com"],
};

const { control } = useForm({ defaultValues: data });

timezone is a selector, while emails is dynamic form element that lets the user add more email addresses. The docs for useFieldArray give this example that I’ve trimmed a little.

const { control } = useForm();

useFieldArray({
  control,
  name: "test", // unique name for your Field Array
});

What wasn’t obvious from the docs is that if you’re supplying defaultValues to useForm then your control is typed with the shape of defaultValues, and useFieldArray picks that up and requires name to be a property of defaultValues. Great, that’s helpful - I want to use the emails property of my defaultValues

useFieldArray({ control, name: "emails" });

Unfortunately this makes Typescript complain:

Type 'string' is not assignable to type 'never'.ts(2322)

fieldArray.d.ts(6, 5): The expected type comes from property 'name' which is declared here on type 'UseFieldArrayProps<{ timezone: string; emails: string[]; }, never, "id">'

The problem is that emails is a flat array of strings, and useFieldArray requires it to be an array of objects. So I need to transform emails to be an array of objects

const data = {
  timezone: "New Zealand",
  emails: [{ address: "craig@example.com" }],
};

and now I can do

useFieldArray({
  control,
  name: "emails",
});

To be fair, the docs “Rules” section says

Does not support flat field array.

But that is pretty cryptic and it’s not obvious that the type error is connected to that rule.

Hopefully this helps someone!