I have the following react component which is a profile button where opens a menu with 3 options: My Profile, Settings and Logout.
The problem is that the onClick event on which is not working (in this case is not printing the console.log)
However, if I remove the useEffect which contains the addEventListener to close the menu when when it is clicked out, the onClick on tags works.
What do I have to do to have it working without removing the EventListener?
React Code:
'use client'
// Importe as bibliotecas necessárias
import React, { useState, useRef, useEffect } from 'react'
//ICON
import { FaCircleUser } from 'react-icons/fa6'
import {
AiOutlineUser,
AiOutlineSetting,
AiOutlineLogout
} from 'react-icons/ai'
const ProfileButton = () => {
// Estado para controlar a exibição do menu
const [isMenuOpen, setIsMenuOpen] = useState(false)
// Referência para o botão de perfil
const profileButtonRef = useRef()
// Função para fechar o menu quando clicar fora do botão
const handleClickOutside = event => {
if (
profileButtonRef.current &&
!profileButtonRef.current.contains(event.target)
) {
setIsMenuOpen(false)
}
}
// Adiciona um event listener para fechar o menu ao clicar fora
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside)
// Remove o event listener ao desmontar o componente
return () => {
document.removeEventListener('mousedown', handleClickOutside)
}
}, [])
return (
<div className="relative inline-block text-left">
{/* Botão de perfil */}
<button
ref={profileButtonRef}
className="text-3xl text-zinc-700 py-2 px-4 rounded-full focus:outline-none cursor-pointer"
onClick={() => setIsMenuOpen(!isMenuOpen)}
>
<FaCircleUser />
</button>
{/* Menu de opções */}
{isMenuOpen && (
<div className="origin-top-right absolute right-0 mt-2 w-50 bg-white border border-gray-300 rounded-md shadow-lg z-50">
<div className="py-1">
<a
href="#"
className="px-4 py-2 text-gray-800 hover:bg-gray-200 flex items-center z-999"
onClick={() => console.log('My Profile')}
>
<AiOutlineUser className="mr-2" size={18} />
My Profile
</a>
<a
href="#"
className="px-4 py-2 text-gray-800 hover:bg-gray-200 flex items-center"
onClick={() => console.log('Settings')}
>
<AiOutlineSetting className="mr-2" size={18} />
Configurações
</a>
</div>
<div className="border-t border-gray-300">
<a
href="#"
className="px-4 py-2 text-gray-800 hover:bg-gray-200 flex items-center"
onClick={() => console.log('logout')}
>
<AiOutlineLogout className="mr-2" size={18} />
Sair
</a>
</div>
</div>
)}
</div>
)
}
export default ProfileButton
Removed the addEventListener but need it to close the menu when click outside.
>Solution :
The issue is due to event propagation. To fix this, you can modify the handleClickOutside function to check if the click is inside the menu as well as the button. If the click is inside either the button or the menu, the function should not close the menu.
Try this one.
import React, { useState, useRef, useEffect } from 'react'
// ... [Other imports]
const ProfileButton = () => {
const [isMenuOpen, setIsMenuOpen] = useState(false)
const profileButtonRef = useRef()
const menuRef = useRef() // Ref for the menu
const handleClickOutside = event => {
if (
profileButtonRef.current &&
!profileButtonRef.current.contains(event.target) &&
menuRef.current && // Ensure menuRef is set
!menuRef.current.contains(event.target) // Check if click is outside the menu
) {
setIsMenuOpen(false)
}
}
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside)
return () => {
document.removeEventListener('mousedown', handleClickOutside)
}
}, [])
return (
<div className="relative inline-block text-left">
{/* ... [Profile Button Code] */}
{/* Menu de opções */}
{isMenuOpen && (
<div ref={menuRef} className="origin-top-right absolute right-0 mt-2 w-50 bg-white border border-gray-300 rounded-md shadow-lg z-50">
{/* ... [Menu Items Code] */}
</div>
)}
</div>
)
}
export default ProfileButton