Reputation: 125
I'm trying to stop the button from clicking again once the dropdown menu is enabled from when the button gets clicked. button clicks -> opens dropdown. the only way the menu can close is from an outside click, and not from the button, that is from the useOnClickOutside "usehooks-ts". The button should only be able to click and open the menu if the menu is closed. thanks in advance if anyone can help with the problem.
https://codesandbox.io/s/funny-wilson-4wbj0?file=/src/App.js (here is the sandbox, but the tailwindcss npm is not working on it.)
import React, { useRef, useState } from "react";
import { useOnClickOutside } from "usehooks-ts";
export const DropDownMenu = () => {
const ref = useRef(null);
const [showMenu, setShowMenu] = useState(false);
const handleClick = () => setShowMenu(!showMenu);
const handleClickOutside = () => setShowMenu(false);
useOnClickOutside(ref, handleClickOutside);
return (
<div className="mt-20">
<button
onClick={handleClick}
className="bg-yellow-300 ml-5 text-sm2
border-solid border-2 border-blue-300"
>
<div>Open Menu</div>
</button>
<div
ref={ref}
className={`absolute top-8 w-240 opacity-0 bg-red-200 ml-20
${showMenu ? "opacity-100 visible" : ""}`}
>
<ul>
<li className="">Menu Item One</li>
<li className="">Menu Item Two</li>
<li className="">Menu Item Three</li>
</ul>
</div>
</div>
);
};
export default DropDownMenu;
Upvotes: 1
Views: 1314
Reputation: 1217
Stop overthinking things. Simply place the ref on the parent component of the button and dropdown, so that it does not detect the child components :)
import React, { useRef, useState } from "react";
import { useOnClickOutside } from "usehooks-ts";
export const DropDownMenu = () => {
const ref = useRef(null);
const [showMenu, setShowMenu] = useState(false);
const handleClick = () => setShowMenu(!showMenu);
const handleClickOutside = () => setShowMenu(false);
useOnClickOutside(ref, handleClickOutside);
return (
<div className="mt-20" ref={ref}> // Place ref here
<button
onClick={handleClick}
className="bg-yellow-300 ml-5 text-sm2
border-solid border-2 border-blue-300"
>
<div>Open Menu</div>
</button>
<div
className={`absolute top-8 w-240 opacity-0 bg-red-200 ml-20
${showMenu ? "opacity-100 visible" : ""}`}
>
<ul>
<li className="">Menu Item One</li>
<li className="">Menu Item Two</li>
<li className="">Menu Item Three</li>
</ul>
</div>
</div>
);
};
export default DropDownMenu;
Upvotes: 0
Reputation: 126
Add condition in handleClick, to check if showMenu is false and then proceed:
const handleClick = () => !showMenu && setShowMenu(!showMenu);
Upvotes: 1