I am making a multiselect component in Next.js and I am using states and setting states. However, this error occurs:
whenever I click this:
This is the code of MultiSelect.tsx:
import { useState } from "react";import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut,} from "@/components/ui/command";interface MultiSelectProps { placeholder: string collections: CollectionType[] value: string[] onChange: (value: string) => void onRemove: (value: string) => void}const MultiSelect: React.FC<MultiSelectProps> = ({ placeholder, collections, value, onChange, onRemove,}) => { const [inputValue, setInputValue] = useState(""); const [open, setOpen] = useState(false); return (<Command className="overflow-visible bg-white"><CommandInput placeholder={placeholder} value={inputValue} onValueChange={setInputValue} onBlur={() => setOpen(false)} onFocus={() => setOpen(true)} /><div className="relative mt-2"> {open && (<CommandGroup className="absolute w-full z-10 top-0 overflow-auto border rounded-md shadow-md"> {collections.map((collection) => (<CommandItem key={collection._id}>{collection.title}</CommandItem> ))}</CommandGroup> )}</div></Command> );};export default MultiSelect;
and here is the code from the ProductForm.tsx:
"use client";import { zodResolver } from "@hookform/resolvers/zod";import { useForm } from "react-hook-form";import { Separator } from "../ui/separator";import { z } from "zod";import { Button } from "@/components/ui/button";import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage,} from "@/components/ui/form";import { Input } from "@/components/ui/input";import { Textarea } from "../ui/textarea";import ImageUpload from "../custom ui/ImageUpload";import { useParams, useRouter } from "next/navigation";import { useEffect, useState } from "react";import toast from "react-hot-toast";import Delete from "../custom ui/Delete";import MultiText from "../custom ui/MultiText";import MultiSelect from "../custom ui/MultiSelect";const formSchema = z.object({ title: z.string().min(2).max(20), description: z.string().min(2).max(500).trim(), media: z.array(z.string()), category: z.string(), collections: z.array(z.string()), tags: z.array(z.string()), size: z.array(z.string()), colors: z.array(z.string()), price: z.coerce.number().min(0.1), expense: z.coerce.number().min(0.1),});interface ProductFormProps { initialData?: ProductType | null; // Must have ? to make it optional}const ProductForm: React.FC<ProductFormProps> = ({ initialData }) => { const router = useRouter(); //const params = useParams(); const [loading, setLoading] = useState(false); const [collections, setCollections] = useState<CollectionType[]>([]); const getCollections = async () => { try{ setLoading(true) const res = await fetch("/api/collections", { method: "GET", }) const data = await res.json() setCollections(data) setLoading(false) }catch(err) { console.log("[collections_GET]", err) toast.error("Something went wrong. Please try again.") } } useEffect(() => { getCollections() }, []) // 1. Define your form. const form = useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: initialData ? initialData : { title: "", description: "", media: [], category: "", collections: [], tags: [], sizes: [], colors: [], price: 0.1, expense: 0.1, }, }); const handleKeyPress = ( e: | React.KeyboardEvent<HTMLInputElement> | React.KeyboardEvent<HTMLTextAreaElement> ) => { if (e.key === "Enter") { e.preventDefault(); } }; // 2. Define a submit handler. const onSubmit = async (values: z.infer<typeof formSchema>) => { // Do something with the form values. // ✅ This will be type-safe and validated. //console.log(values) try { setLoading(true); const url = initialData ? `/api/products/${initialData._id}` : "/api/products"; const res = await fetch(url, { method: "POST", body: JSON.stringify(values), }); if (res.ok) { setLoading(false); toast.success(`Product ${initialData ? "updated" : "created"}.`); window.location.href = "/products"; router.push("/products"); } } catch (err) { console.log("[products_POST]", err); toast.error("Something went wrong. Please try again."); } }; return (<div className="p-10"> {initialData ? (<div className="flex items-center justify-between"><p className="text-heading2-bold">Edit Product</p><Delete id={initialData._id} /></div> ) : (<p className="text-heading2-bold">Create Product</p> )}<Separator className="bg-grey-1 my-4 mb-7" /><Form {...form}><form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8"><FormField control={form.control} name="title" render={({ field }) => (<FormItem><FormLabel>Title</FormLabel><FormControl><Input placeholder="Title" {...field} onKeyDown={handleKeyPress} /></FormControl><FormDescription>The title of the product.</FormDescription><FormMessage /></FormItem> )} /><FormField control={form.control} name="description" render={({ field }) => (<FormItem><FormLabel>Description</FormLabel><FormControl><Textarea placeholder="Description" {...field} rows={5} onKeyDown={handleKeyPress} /></FormControl><FormDescription> The description of the product.</FormDescription><FormMessage /></FormItem> )} /><FormField control={form.control} name="media" render={({ field }) => (<FormItem><FormLabel>Image</FormLabel><FormControl><ImageUpload value={field.value} onChange={(url) => field.onChange([...field.value, url])} onRemove={(url) => field.onChange([ ...field.value.filter((image) => image !== url), ]) } /></FormControl><FormDescription>The image of the product.</FormDescription><FormMessage /></FormItem> )} /><div className="md: grid md:grid-cols-3 md:gap-8"><FormField control={form.control} name="price" render={({ field }) => (<FormItem><FormLabel>Price ($)</FormLabel><FormControl><Input type="number" placeholder="Price" {...field} onKeyDown={handleKeyPress} /></FormControl><FormDescription>The price of the product.</FormDescription><FormMessage /></FormItem> )} /><FormField control={form.control} name="expense" render={({ field }) => (<FormItem><FormLabel>Expense ($)</FormLabel><FormControl><Input type="number" placeholder="Expense" {...field} onKeyDown={handleKeyPress} /></FormControl><FormDescription>The expense of the product.</FormDescription><FormMessage /></FormItem> )} /><FormField control={form.control} name="category" render={({ field }) => (<FormItem><FormLabel>Category</FormLabel><FormControl><Input placeholder="Category" {...field} onKeyDown={handleKeyPress} /></FormControl><FormMessage className="text-red-1" /></FormItem> )} /><FormField control={form.control} name="tags" render={({ field }) => (<FormItem><FormLabel>Tags</FormLabel><FormControl><MultiText placeholder="Tags" value={field.value} onChange={(tag) => field.onChange([...field.value, tag])} onRemove={(tagToRemove) => field.onChange([ ...field.value.filter((tag) => tag !== tagToRemove), ]) } /></FormControl><FormMessage className="text-red-1" /></FormItem> )} /><FormField control={form.control} name="collections" render={({ field }) => (<FormItem><FormLabel>Collections</FormLabel><FormControl><MultiSelect placeholder="Collections" collections={collections} value={field.value} onChange={(_id) => field.onChange([...field.value, _id])} onRemove={(idToRemove) => field.onChange([ ...field.value.filter((collectionId) => collectionId !== idToRemove), ]) } /></FormControl><FormMessage className="text-red-1" /></FormItem> )} /></div><div className="flex gap-10"><Button type="submit" className="bg-blue-1 text-white"> Submit</Button><Button type="button" onClick={() => router.push("/collections")} className="bg-blue-1 text-white"> Discard</Button></div></form></Form></div> );};export default ProductForm;
When I click the multiselect component, I am expecting it to show the current collection list.