I faced a problem with my mobile drowdown menu. I'd like to close dropdown by clicking outside (somewhere, let's say on titels above) of my button and dropdown items.
This is my example.
Menu
const Menu = () => {
const [isMobileNavOpen, setMobileNavState] = useState(false);
const mobileNavRef = useRef();
useOnOutsideClick(mobileNavRef, () => {
if (isMobileNavOpen) setMobileNavState(false);
});
const toggleMobileNav = () => {
setMobileNavState(!isMobileNavOpen);
};
return (
<div>
<div className="dropdown" ref={mobileNavRef}>
<button
className="dropdown-btn"
onClick={toggleMobileNav}
type="button"
>
DROPDOWN BUTTON
</button>
{isMobileNavOpen && (
<div
className="dropdown-menu"
onClick={() => setMobileNavState(false)}
>
<a className="dropdown-item" href="#">
Item1
</a>
<a className="dropdown-item" href="#">
Item2
</a>
</div>
)}
</div>
</div>
);
};
my hook useOnClickOutside
export const useOnOutsideClick = (ref, callback) => {
const handleClick = (e) => {
if (ref.current && ref.current.contains(e.target)) {
callback();
console.log("click");
}
};
useEffect(() => {
document.addEventListener("click", handleClick);
return () => {
document.removeEventListener("click", handleClick);
};
});
};
Please about any help!
Flip the contains logic of your useOutsideClick hook. You want to check of the click event originated from not within the target element the ref is attached to.
const handleClick = (e) => {
if (!ref.current?.contains(e.target)) {
callback();
console.log("click");
}
};
Entire hook
export const useOnOutsideClick = (ref, callback) => {
const handleClick = (e) => {
if (!ref.current?.contains(e.target)) {
callback();
console.log("click");
}
};
useEffect(() => {
document.addEventListener("click", handleClick);
return () => {
document.removeEventListener("click", handleClick);
};
});
};