フォーム系のライブラリはいくつもありますが、動的なフォームは記法でつまづきがちなポイントだと思います。
今回は際レンダリング数が少なく、かなり使われ出しているReact Hook Formの動的なフォームのサンプルです。
まずは動的でないフォーム
こんな感じでOKだと思います。
interface sampleFormInterface {
firstName: string
lastName: string
}
const SampleComponent: React.FC = () => {
const {
register,
handleSubmit,
} = useForm<sampleFormInterface>()
const onSubmit = (data: unknown) => {
console.log(data)
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
placeholder="Basic usage"
{...register('firstName'}
/>
<input
placeholder="Basic usage"
{...register('lastName'}
/>
</form>
)
}
useFormというフックを使って、使う関数やプロパティを準備しています。
種類も多いので、今回の記事ではドキュメントを置いておきます。
useFieldArrayを使って動的に増やせるようにする。
配列対応させるにはuseFieldArrayを使います。
useFieldArrayのnameに配列名(例えばsampleForm)を設定して、
inputのresisterにsampleForm.${index}.firstName
のような形で設定します。
interface sampleFormInterface {
firstName: string
lastName: string
}
const SampleComponent: React.FC = () => {
const {
register,
handleSubmit,
control, // 追加
} = useForm<sampleFormInterface>()
// 追加
const { fields, append } = useFieldArray({
control,
name: 'sampleForm',
keyName: 'key', // デフォルトではidだが、keyに変更。
})
const onSubmit = (data: unknown) => {
console.log(data)
}
// 追加
const addInputForm = () => {
append({ firstName: '', lastName: '' })
}
return (
<>
<form onSubmit={handleSubmit(onSubmit)}>
{/* 変更 */}
<ul>
{fields.map((field, index) => (
<li key={field.key} className="flex space-x-5">
<input
{...register(`sampleForm.${index}.firstName`)}
placeholder="苗字"
/>
<input
{...register(`sampleForm.${index}.lastName`)}
placeholder="名前"
/>
</li>
))}
</ul>
</form>
<button
className="p-2 rounded-full bg-yellow-400"
onClick={addInputForm}
>
追加ボタン
</button>
</>
)
}
ネストさせたい場合は、
useFieldArrayのnameにsampleForm.${index}.nestedArray
のように設定して、
inputのresisterにsampleForm.${index}.nestedArray.${nestedIndex}.firstNameのような形で設定すればOKです。