I am trying to create a react component for rendering a form in react based on data that is fethced from a back-end app via API request . following code is the entire component:
const AnswerSchema = z.object({
id: z.number(),
answer: z.string().nullable(),
rating: z.number().nullable(),
});
const QuestionSchema = z.object({
id: z.number(),
question: z.string(),
description: z.string().nullable(),
type: z.string(),
answers: z.array(AnswerSchema),
});
const TemplateSchema = z.object({
id: z.number(),
title: z.string(),
type: z.string(),
study: z.string(),
questions: z.array(QuestionSchema),
});
const FormEntrySchema = z.object({
id: z.number(),
currentPhase: z.string(),
template: TemplateSchema,
});
type FormEntryValues = z.infer<typeof FormEntrySchema>;
export function FormQuestionsForm() {
const { toast } = useToast();
const [defaultValues,setDefaultValues] = useState<Partial<FormEntryValues>>();
useEffect(() => {
(async () => {
const data = await formService.getFormsForInternshipByStudentId(1);
setDefaultValues(data[0]);
})();
}, []);
const form = useForm<FormEntryValues>({
resolver: zodResolver (FormEntrySchema),
defaultValues,
mode: "onChange",
});
const { fields: questions } = useFieldArray({
name: `template.questions`,
control: form.control,
});
useEffect(() => {
(async () => {
console.log(questions)
})();
}, [questions]);
const useAnswersArray = (questionIndex: number) => {
const { fields: answers, append: appendAnswer, remove: removeAnswer } = useFieldArray({
name: `template.questions.${questionIndex}.answers`,
control: form.control,
});
return { answers, appendAnswer, removeAnswer };
};
function onSubmit(data: FormEntryValues) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
});
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="template.title"
render={({ field }) => (
<FormItem>
<FormLabel>Title</FormLabel>
<p>{field.value}</p>
</FormItem>
)}
/>
<div>
{questions.map((question, index) => (
<FormField
control={form.control}
key={question.id}
name={`template.questions.${index}.question`}
render={({ field }) => (
<FormItem>
<FormLabel className={cn(index !== 0 && "sr-only")}>
URLs
</FormLabel>
<FormDescription className={cn(index !== 0 && "sr-only")}>
Add links for the images
</FormDescription>
<FormControl>
<Input {...question} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
))}
</div>
<Button type="submit">Submit</Button>
</form>
</Form>
);
}
I tried logging the 'defaultValues' and they get set correctly but when logging the 'answers' array (as shown in code) it just logs an empty array and I can't figure out why. The structure of the response is correct and 'template' has an 'answers' field ofcourse, so this is not the problem. Feel free to ask if I forgot to provide needed information. Thanks in advance for your time and help!
you can find more information about the form components a following link: https://ui.shadcn.com/docs/components/form