Home > database >  State in useEffect is not updating
State in useEffect is not updating

Time:04-28

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?

CodePudding user response:

Dependency you have added to useEffect is wrong, you should add menu.current.

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.current]);

CodePudding user response:

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

  • Props change with dependencies
  • States change with dependencies
  • Initial mounted component

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

  • Related