はじめに
動的に追加されたinput
タグへの入力内容を RHF で管理する方法について記した備忘録です。
元の実装例
1.ボタンがクリックされた回数をstate
で保持
2.register
の引数にstate
の値を渡すことで、RHF側のキー が被らないようにする
export function InputProductLink() {
const [clickCount, setClickCount] = useState(0);
return (
<div className="space-y-2">
<p className="font-bold text-xl">作品関連リンク</p>
{Array.from({ length: clickCount }, (_, index) => (
<InputField
type="url"
placeholder="入力されたURLのドメインによってアイコンが決定されます。"
registerName={`productlink${index}`}
key={index}
/>
))}
<div className="flex space-x-2">
<LinkAddButton setClickCount={setClickCount} />
<SaveDBButton />
</div>
</div>
);
}
・このようなキーになります
元の実装例でキーを配列にする方法
register
の引数を下記のように指定することで、配列の要素とすることが出来ます。
registerName={`productlink.${index}`}
useFieldArrayを使った実装例
1.useFormContext
からcontrol
を取り出して、useFieldArrayに渡す。
2.useFieldArray
の引数 name にuseForm
の defaultValueのキー と registerの引数 を渡す。
3.ループにはfields
を使う。
4.要素の追加にはuseFieldArray
からappend
を取り出して使う。
5.要素の削除にはuseFieldArray
からremove
を取り出して使う。
・親コンポーネント側の実装
export function InputProductLink() {
const { control } = useFormContext();
const { fields, append, remove } = useFieldArray({
name: "productLinks",
control,
});
return (
<div className="space-y-2">
<p className="font-bold text-xl">作品関連リンク</p>
{fields.map((field, index) => (
<InputField
key={field.id}
type="url"
placeholder="入力されたURLのドメインによってアイコンが決定されます。"
registerName={`productLinks.${index}`}
/>
))}
<div className="flex space-x-2">
<LinkAddButton append={append} />
<SaveDBButton />
</div>
</div>
);
}
・子コンポーネント側の実装
export function LinkAddButton({ append }: linkAddButtonProps) {
return (
<button
onClick={() => append("")}
className="flex items-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition duration-300"
type="button"
>
<span className="text-xl mr-2">+</span>
<span>追加する</span>
</button>
);
}
さいごに
学習させていただいた記事のリンクです。