Estou com dificuldades para criar um formulário dinâmico com o react-hook-form useFieldArry
, que acrescenta um novo campo/entrada sempre que o último elemento do campo não estiver vazio (para que o usuário não precise se preocupar em adicionar mais entradas).
Embora eu tenha uma solução funcional para casos simples (adicionar dados digitando), ela falha no seguinte caso: ao redefinir o formulário e preenchê-lo programaticamente com dados (por exemplo, clicando em um botão), ele adiciona duas entradas vazias no final. A princípio, pensei que isso estivesse relacionado ao Modo Estrito do React, mas isso acontece até mesmo na versão de produção.
Alguma ideia do porquê isso acontece, uma solução (ou até mesmo uma prática recomendada) para lidar com esse problema?
Aqui está um exemplo prático mínimo:
import { useEffect } from "react";
import { Controller, useFieldArray, useForm, useWatch } from "react-hook-form";
interface FormValues {
items: {
text: string;
}[];
}
export default function DynamicForm() {
const { control, reset } = useForm<FormValues>({
defaultValues: {
items: [{ text: "" }],
},
});
const { fields, append } = useFieldArray({
control,
name: "items",
});
const watchItems = useWatch({
control,
name: "items",
});
useEffect(() => {
if (watchItems && watchItems.length > 0) {
const lastItem = watchItems[watchItems.length - 1];
if (lastItem?.text && lastItem.text.trim() !== "") {
append({ text: "" }, { shouldFocus: false });
}
}
}, [watchItems, append]);
const handleInsertData = () => {
reset({
items: [{ text: "X" }],
});
};
return (
<div className="p-6 max-w-md mx-auto bg-white rounded-xl shadow-md">
<button onClick={handleInsertData}>Insert Data</button>
<h2 className="text-xl font-bold mb-4">Dynamic Form</h2>
<form>
<div className="space-y-4">
{fields.map((field, index) => (
<div key={field.id} className="flex items-start space-x-2">
<div className="flex-grow">
<Controller
control={control}
name={`items.${index}.text`}
render={({ field }) => (
<textarea
{...field}
className="w-full p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Enter text..."
/>
)}
/>
</div>
</div>
))}
</div>
</form>
</div>
);
}
embora eu não tenha 100% de certeza sobre o problema inicial, acredito que ele pode ter origem na sinopse na documentação que diz:
Posso estar errado, mas suspeitando disso, usei "watch" e consegui criar o comportamento que você queria. A solução proposta não pareceu prática, pelo menos neste caso.
se alguém puder confirmar a causa inicial do problema, isso seria apreciado.