I am using react hook form and i am prefilling fetched data from my api into the form fields. My form is on a sheet component which can be opened multiple times.
If i open my component the first time, the fields get prefilled beautifully and everything is fine. But when i close the component again and do the same again, my form fields dont get filled again and using the placeholder, which i don’t want to. I want my prefilled data again.
I am using Next.js with trpc for the api .
Here is my code: Maybe someone had the issue before and can help:
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { CircleAlert, Container as ContainerIcon, Info, LoaderCircle } from "lucide-react";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { ControllerRenderProps, useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { Container, Priority } from "@prisma/client";
import { trpc } from "@/app/_trpc/client";
import React, { Children, useEffect } from "react";
// Form Schema for session options
const SessionFormSchema = z.object({
containerType: z.nativeEnum(Container, {
required_error: "Bitte wählen Sie eine Containerart aus.",
}),
global_priority: z.nativeEnum(Priority, {
required_error: "Bitte wählen Sie eine Priorität aus.",
}),
})
interface PageProps {
sessionId: string
sheetOpen: boolean
}
const SessionSettingsForm = ({ sessionId, sheetOpen }: PageProps) => {
// API functions
// API Route for updating the session options
const updateSessionOptions = trpc.updateSessionOptions.useMutation()
//API Route for fetching the session options
const { data, isLoading } = trpc.getSessionOptions.useQuery({ sessionId })
// Form handling
// Handler for SessionFormSchema
const sessionForm = useForm<z.infer<typeof SessionFormSchema>>({
resolver: zodResolver(SessionFormSchema),
})
useEffect(() => {
if (isLoading || !data || sheetOpen === false) return;
if (data?.containerType !== null && data?.containerType !== undefined && data?.priority !== null && data?.priority !== undefined) {
sessionForm.reset({ containerType: data?.containerType, global_priority: data?.priority });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLoading, sheetOpen, data])
// Submit function for the SessionForm
async function onSessionSubmit(data: z.infer<typeof SessionFormSchema>) {
updateSessionOptions.mutate({
sessionId,
containerType: data.containerType,
global_priority: data.global_priority
})
}
return (
<Form {...sessionForm}>
<form className="grid w-full items-start gap-6"
onSubmit={sessionForm.handleSubmit(onSessionSubmit)}>
<div className="grid gap-2">
<TooltipProvider delayDuration={300}>
<FormField control={sessionForm.control} name="containerType"
render={({ field }) => (
<FormItem>
<FormLabel htmlFor="container">Container</FormLabel>
<Select
onValueChange={(value) => {
sessionForm.setValue('containerType', value as Container)
}}
value={field.value}
disabled={isLoading}
>
<FormControl>
<SelectTrigger
id="container"
className="items-center [&_[data-description]]:hidden"
>
<SelectValue placeholder={isLoading ? (
<span className="flex items-center">
<LoaderCircle className="h-4 w-4 mr-2 animate-spin" />
{"Container werden geladen..."}
</span>
) : "Container auswählen..."} />
</SelectTrigger>
</FormControl>
<SelectContent className={"flex w-full"}>
<SelectItem value={Container.SEA_CONTAINER_20FT}>
<div className="flex items-center gap-3 text-muted-foreground">
<div className="grid gap-0.5">
<p className={"text-foreground"}>
20' Seecontainer
</p>
<p className="flex text-xs gap-2 items-center"
data-description={"Innenmaße mm (LxBxH)"}>
5.898 x 2.352 x 2.390
<Tooltip>
<TooltipTrigger asChild>
<Info className={"size-3.5"} />
</TooltipTrigger>
<TooltipContent side="top" sideOffset={5}>
<p className={"text-xs items-center"}>
Innenmaße mm (LxBxH)
</p>
</TooltipContent>
</Tooltip>
</p>
</div>
</div>
</SelectItem>
<SelectItem value={Container.SEA_CONTAINER_40FT}>
<div className="flex items-center gap-3 text-muted-foreground">
<div className="grid gap-0.5">
<p>
<span className="text-foreground">
40' Seecontainer
</span>
</p>
<p className="flex text-xs gap-2 items-center"
data-description={"Innenmaße mm (LxBxH)"}>
12.032 x 2.352 x 2.395
<Tooltip delayDuration={100}>
<TooltipTrigger asChild>
<Info className={"size-3.5"} />
</TooltipTrigger>
<TooltipContent side="top" sideOffset={5}>
<p className={"text-xs text-foreground items-center"}>
Innenmaße mm (LxBxH)
<br />
</p>
</TooltipContent>
</Tooltip>
</p>
</div>
</div>
</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</TooltipProvider>
</div>
<div className={"grid gap-2"}>
<FormField control={sessionForm.control} name="global_priority"
render={({ field }) => (
<FormItem>
<FormLabel className="flex items-center gap-2">
Priorität
</FormLabel>
<Select
onValueChange={(value) => { sessionForm.setValue('global_priority', value as Priority) }}
value={field.value}
disabled={isLoading}>
<FormControl>
<SelectTrigger className="w-full flex justify-between items-center">
<SelectValue className="text-start" placeholder={isLoading ? (
<>
<span className="flex items-center">
<LoaderCircle className="h-4 w-4 mr-2 animate-spin" />
{"Prioritäten werden geladen..."}
</span>
</>
) : "Priorität auswählen..."} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value={Priority.DYNAMIC}>Dynamisch</SelectItem>
<SelectItem value={Priority.STRICT}>Streng</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
<Button type="button" onClick={sessionForm.handleSubmit(onSessionSubmit)}>Submit</Button>
</form>
</Form>
)
}
export default SessionSettingsForm;
Simon is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.