在useEffect运行后删除事件侦听器,导致scrollIntoView永不熄灭?

问题描述

这是我的代码

const [isScrollLocked,setIsScrollLocked] = useState(false)

  const handleScroll = (section,scrollLocked) => {
    if (!scrollLocked) {
      document.getElementById(section).scrollIntoView()
      document.querySelector('body').classList.add('overflow-hidden')
      setIsScrollLocked(true)
      setTimeout(() => {
        document.querySelector('body').classList.remove('overflow-hidden')
        setIsScrollLocked(false)
      },1500)
    }
  }

  useEffect(() => {
    const handler = (e) => handleScroll(nextSection,isScrollLocked)

    document.addEventListener('scroll',handler)

    // cleanup callback,that will be called before the effect runs again

    return () => document.removeEventListener('scroll',handler)
  },[nextSection,isScrollLocked])

似乎在useEffect之后运行的回调清理正在进行,因此handleScroll内部的scrollIntoView永远不会发生。但是,如果我在console.log触发之前或之后触发。如果删除回调,scrollIntoView会正常工作,但是我会堆积成千上万的滚动事件并使应用程序崩溃。

如果有人能弄清为什么回调清理会产生这种效果,并向我解释一下,我真的很想知道。

解决方法

问题在于您的setTimeoutuseEffect是如何相互作用的。每当useEffect更改时,您的isScrollLocked就会运行。由于您的setTimeout正在更改isScrollLocked,因此看起来useEffect在1.5秒后开始运行。

尝试删除isScrollLocked观察者:

  const [isScrollLocked,setIsScrollLocked] = useState(false);

  const handleScroll = (section) => {
    if (!isScrollLocked) {
      document.getElementById(section).scrollIntoView();
      document.querySelector("body").classList.add("overflow-hidden");
      setIsScrollLocked(true);
      setTimeout(() => {
        document.querySelector("body").classList.remove("overflow-hidden");
        setIsScrollLocked(false);
      },1500);
    }
  };

  useEffect(() => {
    const handler = (e) => handleScroll(nextSection);
    document.addEventListener("scroll",handler);

    // cleanup callback,that will be called before the effect runs again
    return () => document.removeEventListener("scroll",handler);
  });

这里是链接:https://codesandbox.io/s/react-hooks-counter-demo-forked-7n064

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...