I have a Navbar component with an "Account" button that should toggle a dropdown menu. The dropdown should open when clicked and close when clicking outside or clicking the button again. However, clicking "My Account" only opens the menu but doesn't close it when clicked again.
Navbar.jsx
import { useState } from 'react';
import { Link } from 'react-router-dom';
import AccountDropdown from '../AccountDropdown';
const Navbar = () => {
const [isAccountMenuOpen, setIsAccountMenuOpen] = useState(false);
const toggleAccountMenu = (event) => {
event.stopPropagation();
setIsAccountMenuOpen((prev) => !prev);
};
const handleAccountMenuClose = () => {
if (isAccountMenuOpen) setIsAccountMenuOpen(false);
};
return (
<nav>
<button onClick={toggleAccountMenu}>My Account</button>
{isAccountMenuOpen && <AccountDropdown onClose={handleAccountMenuClose} />}
</nav>
);
};
export default Navbar;
AccountDropdown.jsx
import { useEffect, useRef } from 'react';
const AccountDropdown = ({ onClose }) => {
const dropdownRef = useRef(null);
useEffect(() => {
const handleClickOutside = (event) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
onClose();
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, [onClose]);
return (
<div ref={dropdownRef}>
<button onClick={onClose}>Close</button>
<a href="/profile">Profile</a>
<a href="/logout">Log Out</a>
</div>
);
};
export default AccountDropdown;
Clicking "My Account" always opens the menu, but clicking it again doesn't close it. How can I properly toggle the dropdown?
I have a Navbar component with an "Account" button that should toggle a dropdown menu. The dropdown should open when clicked and close when clicking outside or clicking the button again. However, clicking "My Account" only opens the menu but doesn't close it when clicked again.
Navbar.jsx
import { useState } from 'react';
import { Link } from 'react-router-dom';
import AccountDropdown from '../AccountDropdown';
const Navbar = () => {
const [isAccountMenuOpen, setIsAccountMenuOpen] = useState(false);
const toggleAccountMenu = (event) => {
event.stopPropagation();
setIsAccountMenuOpen((prev) => !prev);
};
const handleAccountMenuClose = () => {
if (isAccountMenuOpen) setIsAccountMenuOpen(false);
};
return (
<nav>
<button onClick={toggleAccountMenu}>My Account</button>
{isAccountMenuOpen && <AccountDropdown onClose={handleAccountMenuClose} />}
</nav>
);
};
export default Navbar;
AccountDropdown.jsx
import { useEffect, useRef } from 'react';
const AccountDropdown = ({ onClose }) => {
const dropdownRef = useRef(null);
useEffect(() => {
const handleClickOutside = (event) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
onClose();
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, [onClose]);
return (
<div ref={dropdownRef}>
<button onClick={onClose}>Close</button>
<a href="/profile">Profile</a>
<a href="/logout">Log Out</a>
</div>
);
};
export default AccountDropdown;
Clicking "My Account" always opens the menu, but clicking it again doesn't close it. How can I properly toggle the dropdown?
Share Improve this question asked Feb 4 at 8:10 in43shin43sh 9432 gold badges14 silver badges37 bronze badges2 Answers
Reset to default 1Verify that your onClick handler correctly toggles the state. For example, using useState:
const [isOpen, setIsOpen] = useState(false);
const toggleDropdown = (e) => {
e.stopPropagation(); // Prevents event bubbling
setIsOpen((prev) => !prev);
};
Because you are using ref to close dropdown while clicking outside of the dropdown content. So once the dropdown is opened "My account" button also considered as a ouside click, it won't match with the outer click function which is you called. That's why dropdown closed and reopened when you click "My account" button.
So for your simple case, just modify either one:
const toggleAccountMenu = (event) => {
if(isAccountMenuOpen) return;
setIsAccountMenuOpen(true);
};
Or second case:
<nav>
<button style={{ pointerEvents: isAccountMenuOpen ? 'none' : 'all' }}
onClick={toggleAccountMenu}>My Account</button>
{isAccountMenuOpen && <AccountDropdown onClose={handleAccountMenuClose}
/>}
</nav>