Javascript removeEventListener不工作(函数不是匿名的,与addEventListener完全相同!!)

Javascript removeEventListener不工作(函数不是匿名的,与addEventListener完全相同!!),javascript,reactjs,use-effect,removeeventlistener,Javascript,Reactjs,Use Effect,Removeeventlistener,我已经搜罗了每一篇文章,说removeEventListener不起作用。其中99%是因为要删除的函数与创建的函数不匹配。但是在我的例子中,函数是完全相同的,但是事件根本没有被删除 其思想是,当组件状态isOpen[1]==true时,事件侦听器应该关闭。但事实并非如此。我所做的一切似乎都不能让removeEventListener工作!!我在组件中的任何地方都进行了登录,所有事情都按照正确的顺序进行useEffect在正确的时间接收到正确的信号以激活removeEventListener,但侦

我已经搜罗了每一篇文章,说removeEventListener不起作用。其中99%是因为要删除的函数与创建的函数不匹配。但是在我的例子中,函数是完全相同的,但是事件根本没有被删除

其思想是,当组件状态
isOpen[1]==true
时,事件侦听器应该关闭。但事实并非如此。我所做的一切似乎都不能让removeEventListener工作!!我在组件中的任何地方都进行了登录,所有事情都按照正确的顺序进行
useEffect
在正确的时间接收到正确的信号以激活
removeEventListener
,但侦听器仍然存在

请帮忙。疯了

更新:在所有建议之后,这是当前代码。虽然变化不大,但我已经尝试了您的所有解决方案(谢谢)

const[isOpen,setIsOpen]=useState([“”,false]);
const[panelHeight,setPanelHeight]=useState({skills:0,contact:0});
const[envOpen,setEnvOpen]=useState(false);
常量[scrollState,setScrollState]=使用状态(“显示”);
//向下滚动时隐藏导航按钮,向上滚动时显示
var lastScrollTop=window.pageYOffset | | window.scrollTop;
函数scrollDetect(){
var st=window.pageYOffset | | document.documentElement.scrollTop;
如果(stlastScrollTop){
setScrollState(“隐藏”);
}
lastScrollTop=st{
让newState=!state;
setIsOpen([标题,新闻状态]);
};
const setHeight=(标题、高度)=>{
setPanelHeight((prevState)=>({…prevState,[标题]:height});
};
常量信封页=()=>{
setEnvOpen(真);
};
常量信封关闭=()=>{
setEnvOpen(假);
};
useffect(()=>{
如果(!isOpen[1]){
文档。添加的文本列表器(“滚动”,滚动检测);
}
}, []);
useffect(()=>{
if(等参[1]){
document.removeEventListener(“滚动”,scrollDetect);
}
},[isOpen]);
更新:此处回购

使用create react应用程序创建,因此您可以在第一次使用效果时添加“如果”语句

只是为了确保不会再次添加事件侦听器

useEffect(() => {
    console.log("useEffect1")
    console.log(isOpen[1]);
    if(!isOpen)
       document.addEventListener("scroll", scrollDetect);
  }, []);
同时更新

我们可以使用“useCallback”来保持对同一个函数对象的引用,这样我们就可以确保我们使用的是同一个函数,试一试

const scrollDetect = useCallback(() => {
    var st = window.pageYOffset || document.documentElement.scrollTop;
    if (st < lastScrollTop) {
      setScrollState("show");
    } else if (st > lastScrollTop) {
      setScrollState("hide");
    }
    lastScrollTop = st <= 0 ? 0 : st;
},[]);
constScrollDetect=useCallback(()=>{
var st=window.pageYOffset | | document.documentElement.scrollTop;
如果(stlastScrollTop){
setScrollState(“隐藏”);
}

lastScrollTop=st
scrollDetect
是箭头函数,您可以为组件的每个渲染创建新函数。 在removeEventLister中,您需要传递在addEventListener中使用的相同函数。但这永远不会发生)

对于这样的事情,你可以把它写成函数

  function scrollDetect() {
    var st = window.pageYOffset || document.documentElement.scrollTop;
    if (st < lastScrollTop) {
      setScrollState("show");
    } else if (st > lastScrollTop) {
      setScrollState("hide");
    }
    lastScrollTop = st <= 0 ? 0 : st;
  };
函数scrollDetect(){ var st=window.pageYOffset | | document.documentElement.scrollTop; 如果(stlastScrollTop){ setScrollState(“隐藏”); } lastScrollTop=st lastScrollTop){ setScrollState(“隐藏”); } lastScrollTop=st{ 让newState=!state; setIsOpen([标题,新闻状态]); }; const setHeight=(标题、高度)=>{ setPanelHeight((prevState)=>({…prevState,[标题]:height}); }; 常量信封页=()=>{ setEnvOpen(真); }; 常量信封关闭=()=>{ setEnvOpen(假); }; useffect(()=>{ console.log(“useffect1”) console.log(isOpen[1]); 文档。添加的文本列表器(“滚动”,滚动检测); }, []); useffect(()=>{ console.log(“useffect2”) console.log(isOpen[1]); document.removeEventListener(“滚动”,scrollDetect); },[isOpen]); ...
答案是没有答案。什么都不起作用。我将以更连贯的方式重新发布此消息,希望有人能提供帮助。感谢大家的回答。

从技术上讲,您的函数可能有一个名称,但是,这并不能免除使用匿名函数导致的相同问题。如果您正在创建您传递给removeEventListener的函数与用于添加它的函数在不同的上下文中,它是一个不同的函数,无论它们是否共享名称/源代码。非常感谢Kevin,我一点也没有想到。不幸的是,更改为常规函数并不能解决问题,但是,如果你仍在创建常规函数,而你现在正在创建一个,这是同一个问题。你要删除的函数与你要添加的函数不同。它们可能是等价的,但并不完全相等。我猜你的第二个效果是出于某种原因在第一个效果之前执行的,但它是很难说。是否可以尝试传递
isOpen
scroll
作为依赖项检测(在第二个参数数组中)对于你的两个
useffect
s?你也可以在每个效果的末尾添加一个log语句,这样你就可以知道哪个是先执行的。获得更多信息后,请随时更新,我会看看我是否能帮上忙!嗨,谢谢你的回复^ ^你说我应该添加“滚动”是什么意思作为依赖项?你是指
scrollDetect
函数吗?如果我将其添加到依赖项数组中,我会在VSCode中得到一个警告,我应该将
scrollDetect
包装在
useCallback
钩子中。这是一个非常好的答案,我从来没有将箭头函数视为分配匿名函数,我总是认为它们与功能!但是…它做到了
...
function scrollDetect(){
    var st = window.pageYOffset || document.documentElement.scrollTop;
    if (st < lastScrollTop) {
      setScrollState("show");
    } else if (st > lastScrollTop) {
      setScrollState("hide");
    }
    lastScrollTop = st <= 0 ? 0 : st;
  };

  const setOpen = ([title, state]) => {
    let newState = !state;
    setIsOpen([title, newState]);
  };

  const setHeight = (title, height) => {
    setPanelHeight((prevState) => ({ ...prevState, [title]: height }));
  };

  const envelopeOpen = () => {
    setEnvOpen(true);
  };

  const envelopeClose = () => {
    setEnvOpen(false);
  };

  useEffect(() => {
    console.log("useEffect1")
    console.log(isOpen[1]);
    document.addEventListener("scroll", scrollDetect);
  }, []);

  useEffect(() => {
    console.log("useEffect2")
    console.log(isOpen[1]);
      document.removeEventListener("scroll", scrollDetect);
  }, [isOpen]);
...