I have this component that when I click on the button it toggles the state of isMenuActive, the problem comes when implementing the function inside the useEffect, for a strange reason when I try to access to the value of isMenuActive inside the closeTooltip function it always reflects false, even though the value of isMenuActive has changed to true.
import { useState, useEffect, useRef } from "react";
import Tooltip from "./Tooltip";
export default function Navbar() {
const [isMenuActive, setIsMenuActive] = useState(false);
const menu = useRef(null);
const handleOnClick = (e) => {
setIsMenuActive((prev) => !prev);
};
useEffect(() => {
const closeTooltip = (e) => {
if (menu.current && !menu.current.contains(e.target)) {
//Here isMenuActive is always false, even after using handleOnClick func
console.log(isMenuActive);
}
};
document.addEventListener("click", closeTooltip, true);
return () => document.removeEventListener("click", closeTooltip, true);
}, [menu]);
return (
<button
className="navbar__notifications"
aria-label="Notificaciones"
name="notification"
onClick={handleOnClick}
ref={menu}
>
{isMenuActive && <Tooltip title="Notificaciones" />}
</button>
);
}
Any idea of why is this happening?
menu
(with useRef
) always refers to the same object, so useEffect
won't be triggered for every change of menu
(even though menu.current
).
useEffect
is only triggered in 3 cases
The log you get from closeTooltip
is from the initial useEffect
call (initial mounted component)
For the fix, you should add isMenuActive
(state changes) in the dependency list of useEffect
instead. That will keep listening to isMenuActive
state changes and update your closeTooltip
event accordingly.
useEffect(() => {
const closeTooltip = (e) => {
if (menu.current && !menu.current.contains(e.target)) {
//Here isMenuActive is always false, even after using handleOnClick func
console.log(isMenuActive);
}
};
document.addEventListener("click", closeTooltip, true);
return () => document.removeEventListener("click", closeTooltip, true);
}, [isMenuActive]);
You can check this sandbox for the test