代码之家  ›  专栏  ›  技术社区  ›  Darigan

clearTimeout将一个函数中的计时器与另一个函数(React.js)一起超时

  •  0
  • Darigan  · 技术社区  · 3 周前

    代码用于 Navbar 。我想要这个,当鼠标离开它时,这个计时器启动了,但当这个时间还在计数时,如果我把鼠标移到 导航栏 ,计时器计数被停止并显示为无,不应用。问题是当我将鼠标移出 导航栏 然后计时器再次不停止,并且在计数下拉显示结束时消失。

    这是我的代码:

    const [navOver, setNavOver] = useState(false);
    const [currentItem, setCurrentItem] = useState("");
    
    let timer;
    
    const handleMouseOver = (item) => {
      setNavOver(true);
      clearTimeout(timer);
      for (var i = 0; i < dropdown.length; i += 1) {
        if (dropdown[i].style.display === "none") {
          dropdown[i].style.display = "block";
        }
      }
      if (!currentItem) {
        setCurrentItem(item);
      }
    };
    
    const handleMouseOut = (event) => {
      if (!event.relatedTarget || !event.relatedTarget.closest("nav")) {
        setNavOver(false);
        timer = setTimeout(() => {
          for (var i = 0; i < dropdown.length; i += 1) {
            dropdown[i].style.display = "none";
          }
        }, 700);
      }
    };

    和jsx代码:

    <nav onMouseOut={handleMouseOut}>
      <ul className="lg:flex hidden gap-4 ps-4">
        {navLinks.map((item, index) => {
          return (
            <>
              <li key={index} className="z-50">
                <Link
                  to={item.href}
                  onMouseOver={() => {
                    handleMouseOver(item);
                    setCurrentItem(item);
                  }}
                >
                  {item.label}
                </Link>
              </li>
              <div className="dropdownContainer">
                // there was dropdown component
              </div>
            </>
          );
        })}
      </ul>
    </nav>

    我想把计时器停下来 handleMouseOut 使用 handleMouseOver 作用

    1 回复  |  直到 3 周前
        1
  •  2
  •   Scott Z    3 周前

    自从 let timer; 在组件的主体中声明,每次渲染都会重新定义它。所以到那时 handleMouseOver 正在尝试运行 clearTimeout(timer); 计时器实际上是未定义的。在这种情况下,ref可以用于保存的值/引用 timer 在渲染之间。

    所以这样做应该会得到你想要的。

    const timerRef=useRef(null);
    
    const handleMouseOver = (item) => {
      setNavOver(true);
      if(timerRef.current) clearTimeout(timerRef.current);
      
      for (var i = 0; i < dropdown.length; i += 1) {
        if (dropdown[i].style.display === "none") {
          dropdown[i].style.display = "block";
        }
      }
      if (!currentItem) {
        setCurrentItem(item);
      }
    };
    
    const handleMouseOut = (event) => {
      if (!event.relatedTarget || !event.relatedTarget.closest("nav")) {
        setNavOver(false);
        timerRef.current = setTimeout(() => {
          for (var i = 0; i < dropdown.length; i += 1) {
            dropdown[i].style.display = "none";
          }
        }, 700);
      }
    };
    

    您还可能会造成内存泄漏,因此如果页面卸载,您也应该清理计时器,方法是在返回类似的useEffect时进行清理。

    useEffect(()=>{
       return()=> {
         if(timerRef.current) clearTimeout(timerRef.current);
         }
    },[])