ui
ui copied to clipboard
❌ DEFAULT VALUES DON'T WORK ❌
'use client';
import { z } from 'zod';
import { Button } from './ui/button';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from './ui/form';
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from './ui/sheet';
import useCustomForm from '@/hooks/useCustomForm';
import { Checkbox } from './ui/checkbox';
import { trpc } from '@/app/_trpc/client';
import { useEffect, useState } from 'react';
import { serverClient } from '@/app/_trpc/serverClient';
function AssignStudents({
teacher_id,
students,
}: {
teacher_id: string;
students: Awaited<ReturnType<(typeof serverClient)['getStudents']>>;
}) {
const utils = trpc.useUtils();
const teacher = trpc.getTeacher.useQuery({
id: teacher_id,
});
const items = [
...students.map((student) => ({
id: student?.id,
label: student?.firstname,
})),
] as const;
const FormSchema = z.object({
items: z.array(z.string().cuid()),
});
const [defaultStudents, setDefaultStudents] = useState<string[] | undefined>(
[]
);
useEffect(() => {
const ids = teacher.data?.students.map((student) => student.student_id);
setDefaultStudents(ids);
}, [teacher.data?.students]);
const [openSheet, setOpenSheet] = useState(false);
const [form] = useCustomForm({
formSchema: FormSchema,
defaultValues: {
items: defaultStudents,
},
});
const assignStudentToTeacher = trpc.assignStudentToTeacher.useMutation({
onSuccess() {
utils.getTeacher.invalidate();
},
});
const deleteStudentFromTeacher = trpc.deleteStudentFromTeacher.useMutation({
onSuccess() {
utils.getTeacher.invalidate();
},
});
async function onSubmit(data: z.infer<typeof FormSchema>) {
// get checked values
const checkedStudents = data.items;
// get unchecked values
const uncheckedStudents = students
.filter((student, i) => {
const sId = data.items[i];
return sId !== student?.id;
})
.map((student) => student?.id);
console.log(checkedStudents);
console.log(uncheckedStudents);
// setOpenSheet(false);
}
return (
<Sheet open={openSheet} onOpenChange={setOpenSheet}>
<SheetTrigger asChild>
<Button variant="default">Assign Students</Button>
</SheetTrigger>
<SheetContent className="">
<SheetHeader>
<SheetTitle>Assign Students</SheetTitle>
</SheetHeader>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8 mt-5"
>
<FormField
control={form.control}
name="items"
render={() => (
<FormItem>
{items.map((student) => (
<FormField
key={student.id}
control={form.control}
name="items"
render={({ field }) => {
return (
<FormItem
key={student.id}
className="flex flex-row items-start space-x-3 space-y-0"
>
<FormControl>
<Checkbox
checked={field.value?.includes(student.id)}
onCheckedChange={(checked) => {
return checked
? field.onChange([
...field.value,
student.id,
])
: field.onChange(
field.value?.filter(
(value: string) =>
value !== student.id
)
);
}}
/>
</FormControl>
<FormLabel className="font-normal">
{student.label}
</FormLabel>
</FormItem>
);
}}
/>
))}
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
</SheetContent>
</Sheet>
);
}
export default AssignStudents;
May be worth checking what the first value passed for 'defaultStudents' is defaults is cached on first render, caught me out also, fixed by firing a useEffect that triggers form.reset
eg:
useEffect(() => {
form.reset();
}, [defaultStudents]);
@aronedwards91 When I write hard coded default values, it works, but with dynamic data, doesn't work
Does sound like a cached value could be an issue, maybe provide .reset() with the new 'defaultValues' ? https://react-hook-form.com/docs/useform/reset
@aronedwards91 which data is cached?
Possibly the initial defaultValues see this thread https://github.com/shadcn-ui/ui/issues/1361
@aronedwards91 they're talking about the select component, I'm dealing with a checkbox
I have ran into a checkbox issue like this before but on a different UI library (Chakra), and I am not sure if it was specific to the UI library. In my case the checkbox was being controlled by a some condition based on user interactions somewhere else on the site - so not through a user manually clicking the checkbox.
My hack was to set the key of the checkbox to the toString()
of the dynamic true
or false
value. Likely not the best/performant solution, but it may work for you!
I'm facing the same problem. The input is of type text. The problem disappear when I provide a default Values, but it's very awful in a big form.
@aymanechaaba1 how did you deal with it?
I got this problem, too.
Is this problem still going on? I think this is critical issue.
@jackypan1989 @0Chan-smc That works for me now
This issue is related to how you are using react-hook-form
, and not the component library.
defaultValues
are cached, and need to be manually set if you want to change them, as you can read in their docs
@NatanCieplinski You're right, the issue is a react-hook-form issue, and default values need to be defined.