🦊
【React Hook Form】useFieldArrayの使い方
概要
Reactでフォームを実装する際にはReact Hook Form
を使っているのですが、要素が可変のフォームを実装したのでまとめておきます。
結論としてはuseFieldArray
を使うことで実現できました。
基本
import { useForm, useFieldArray } from 'react-hook-form';
export const FormComponent = () => {
const { register, handleSubmit, control } = useForm({
defaultValues: {
emails: [{ email: '' }],
},
});
const { fields, append } = useFieldArray({
name: 'emails',
control,
});
const onSubmit = (data) => {
const { emails } = data;
console.log(emails);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
{fields.map((field, index) => (
<>
<input
key={field.id}
type="email"
{...register(`emails.${index}.email`)}
/>
</>
))}
</div>
<button type="button" onClick={() => append({ email: '' })}>
add
</button>
<button type="submit">submit</button>
</form>
);
};
useFieldArrayにはuseFormのcontroll
と、一意のname
を指定します。
fields
には配列が入っているので、それをmapで展開します。その際にkeyにはindexではなくfield.id
を指定しましょう。
要素を追加する場合はuseFieldArrayから返ってくるappend
を使うことでfieldsに追加できます。
要素の削除
import { useForm, useFieldArray } from 'react-hook-form';
export const FormComponent = () => {
const { register, handleSubmit, control } = useForm({
defaultValues: {
emails: [{ email: '' }],
},
});
const { fields, append, remove } = useFieldArray({
name: 'emails',
control,
});
const onSubmit = (data) => {
const { emails } = data;
console.log(emails);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
{fields.map((field, index) => (
<>
<input
key={field.id}
type="email"
{...register(`emails.${index}.email`)}
/>
<button type="button" onClick={() => remove(index)}>
remove
</button>
</>
))}
</div>
<button type="button" onClick={() => append({ email: '' })}>
add
</button>
<button type="submit">submit</button>
</form>
);
};
要素を削除したい場合はremove
を使用します。
removeはどの要素を削除するのかを引数に指定できるので、indexを指定します。
要素を入れ替える
import { useForm, useFieldArray } from 'react-hook-form';
export const FormComponent = () => {
const { register, handleSubmit, control } = useForm({
defaultValues: {
emails: [{ email: '' }],
},
});
const { fields, append, remove, replace } = useFieldArray({
name: 'emails',
control,
});
const onSubmit = (data) => {
const { emails } = data;
console.log(emails);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
{fields.map((field, index) => (
<>
<input
key={field.id}
type="email"
{...register(`emails.${index}.email`)}
/>
<button type="button" onClick={() => remove(index)}>
remove
</button>
</>
))}
</div>
<button type="button" onClick={() => append({ email: '' })}>
add
</button>
<button
type="button"
onClick={() => {
replace([{ email: 'new email' }]);
}}
>
replace
</button>
<button type="submit">submit</button>
</form>
);
};
要素を新しく入れ替えたい場合はreplace
を使用します。
replaceを使うことでfieldsに入っている値を削除して、新しい値を格納できます。
replaceの引数には新しく格納する値を指定しましょう。
自分の場合はAPIから取得したデータをもとに新たにフォーム要素を差し替えたい場面があったのでreplaceを使用しました。
Discussion
ぼくも
move
の場合のデモにチャレンジしてみました。auto-animate
で少しアレンジしてみました。demo code.