I’m using a fieldArray to build a form using react-hook-form. This form is used for both create and update an user and i’m also using the “values” prop from react-hook-form. The field using the fieldArray api has 2 simple time inputs, and there’s a button “add” that you can click to render more time inputs (it starts empty).
form default
added field
The problem is, when i’m fetching data before this form and it has any breakTime (the array field name) it is not rendered immediately in the ui. But, when I click to add it renders all the fields fetched from the api. (see images below)
all fields filled, except the array field
after clicking on add button of array field
My code below:
const form = useForm<OperatorOrManageData>({
resolver: zodResolver(operatorOrManagerSchema),
defaultValues: initializeDefaultValues(),
mode: "all",
values: data,
})
const { fields, append, remove } = useFieldArray({
name: "breakTime",
control: form.control,
})
{fields.map((field, index) => (
<div className="flex w-full flex-row items-center gap-3" key={field.id}>
<div className="w-56 flex-row items-start whitespace-nowrap rounded-full bg-primaryBlue-100 px-4 py-2">
<span>Horário de intervalo</span>
</div>
<FormField
control={form.control}
name={`breakTime.${index}.start` as const}
render={({ field }) => (
<FormItem>
<FormControl>
<div className="relative">
<Input
{...field}
type="time"
className="flex rounded-full border border-primaryGray-400 py-2 pe-4 ps-12"
value={field.value}
/>
<div className="absolute left-0 top-1/2 z-10 flex h-10 w-10 -translate-y-1/2 transform items-center justify-center rounded-s-full bg-primaryGray-100">
<span>De</span>
</div>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name={`breakTime.${index}.finish` as const}
render={({ field }) => (
<FormItem>
<FormControl>
<div className="relative">
<Input
{...field}
type="time"
className="flex rounded-full border border-primaryGray-400 py-2 pe-4 ps-12"
value={field.value}
/>
<div className="absolute left-0 top-1/2 z-10 flex h-10 w-10 -translate-y-1/2 transform items-center justify-center rounded-s-full bg-primaryGray-100">
<span>Até</span>
</div>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant={"destructive"}
size={"sm"}
type="button"
className="rounded-full p-2"
onClick={() => remove(index)}
>
<Trash />
</Button>
</TooltipTrigger>
<TooltipContent className="border-0 bg-red-500 text-secondaryWhite-100 dark:border-0 dark:bg-red-500">
<p>Excluir</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
))}
I’ve tried to use controlled field array as in the docs https://react-hook-form.com/docs/usefieldarray but didn’t work.
@Ja1za1, Hey there, You can fetch your data from the parent component and use a loading state until data is fetched.
This is the Parent
const Parent = () => {
const {data, isLoading} = fetch("url");
if(isLoading) {return <Loading />}
if(data) {
return <Child data={data} />
}
}
return null
This is the Child
//CHILD
const Child = ({data}) => {
const form = useForm<OperatorOrManageData>({
resolver: zodResolver(operatorOrManagerSchema),
defaultValues: initializeDefaultValues(),
mode: "all",
values: data,
})
//...other codes
}
Careful, form.watch("inputFieldName")
method will return fields array with value undefined if you use disabled.
eg: cars:[{value: undefined]
.
Use readOnly
with the Input component not with the FormField.
eg: <FormField disabled control={form.control} name={` urls.${index}.value`} ..... />
❌
eg: <Input disabled placeholder="type here" />
❌
eg: <Input readOnly placeholder="type here" />
✔