In the following code, I wanted to put all the collapsible logic into the Collapsible
component. However, the collapse is being triggered by a button that’s outside of Collapsible
. So I made Collapsible
to react to that button’s onClick
. For that, I had to use useEffect
:
// JS:
const [collapsed, setCollapsed] = useState(true);
// JSX:
<div className="flex w-full justify-between">
<Heading size="sm" className="shrink-0">
Tags
</Heading>
<Button
variant="link"
onClick={() => setCollapsed(!collapsed)}
className="md:hidden"
>
{collapsed ? (
<IconChevronDown size={20} />
) : (
<IconChevronUp size={20} />
)}
</Button>
</div>
<Collapsible collapsed={collapsed} className="md:hidden">
<div className="mt-4 w-full">{renderedTags}</div>
</Collapsible>
Inside Collapsible
, I have this:
useEffect(() => {
if (collapsed) {
setMaxHeight('0px');
} else if (contentRef.current) {
setMaxHeight(`${contentRef.current.scrollHeight}px`);
}
}, [collapsed]);
Do you think using useEffect
like this to react to user input is bad practice? To prevent that, I could create a useCollapsible
hook, but that would separate the collapsible logic from the Collapsible
component.