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