I'm currently working on a project, and now I'm creating a Select component using a design pattern that I discovered. The implementation looks great, but something seems to be wrong as the useState doesn't appear to be working. I'm relatively new to Next.js/React, so maybe it's a simple logic error.
Here are the main code:
'use client';
import Image from 'next/image';
import { Select } from '@/components/ui/select';
import { ferramentas } from '@/libs/ferramentas';
import { useState } from 'react';
import { Check } from 'lucide-react';
export default function Ferramentas() {
const [tool, setTool] = useState('');
const handleSelect = (option: string) => {
console.log(option);
setTool(option);
};
return (
<div className="ml-16">
<Select.Root className="w-[500px]" selected={tool}>
<Select.Content>
{ferramentas.map((ferramenta) => (
<Select.Option key={ferramenta.item_id} onClick={() => handleSelect(ferramenta.item_id)}>
<div className="flex items-center gap-3">
<Image alt={ferramenta.name} src={`https://render.albiononline.com/v1/item/${ferramenta.item_id}.png`} width={32} height={32} />
{ferramenta.name}
</div>
{tool === ferramenta.item_id ? <Check /> : null}
</Select.Option>
))}
</Select.Content>
</Select.Root>
<h1>{tool}</h1>
</div>
);
}
Select.Root
'use client';
import { SelectProps } from '@/components/global-types';
import { ChevronDown, ChevronUp } from 'lucide-react';
import { useState } from 'react';
import { twMerge } from 'tailwind-merge';
export default function SelectRoot({ className, children, selected, ...props }: SelectProps) {
const [open, setOpen] = useState(false);
return (
<div
className={twMerge('group rounded relative cursor-pointer h-8 m-5 px-2 flex items-center flex-row-reverse justify-between bg-white', className)}
onClick={() => setOpen(!open)}
{...props}
>
{open ? <ChevronUp className="group-hover:opacity-70" /> : <ChevronDown className="group-hover:opacity-70" />}
{selected}
{open && children}
</div>
);
}
Select.Content
import { ReactNode } from 'react';
export default function SelectContent({ children }: { children: ReactNode }) {
return <div className="absolute top-full left-0 mt-1 overflow-y-scroll h-64 rounded bg-zinc-800 p-2 w-full">{children}</div>;
}
SelectOption
import { OptionProps } from '@/components/global-types';
import { twMerge } from 'tailwind-merge';
export default function SelectOption({ children, className, ...props }: OptionProps) {
return (
<div className={twMerge('flex items-center justify-between cursor-pointer hover:bg-zinc-700 text-white h-8 px-2 whitespace-nowrap rounded', className)}>
{children}
</div>
);
}
I tried create a function to setState, or setState directly on onClick but never happens, the states don't change.
The issue is that you're passing an onClick
prop to the SelectOption
component, but it's not being used.
You need to add it like this:
export default function SelectOption({ children, className, onClick, ...props }: OptionProps) {
return (
<div onClick={onClick} className={twMerge('flex items-center justify-between cursor-pointer hover:bg-zinc-700 text-white h-8 px-2 whitespace-nowrap rounded', className)}>
{children}
</div>
);
}
Or spreading the props directly by doing the following:
<div
className="your-current-classes"
{...props}
>
{children}
</div>