我有一个用例,我想用React钩子解决它,但是它没有按我预期的那样工作。
谢谢。
答案 0 :(得分:3)
该组件一次添加事件侦听器:仅在安装时。那时,它添加了在该特定时间点被该特定handleScroll
值“捕获”的isHeaderMoved
侦听器。每当滚动页面时,将被调用的是具有初始isHeaderMoved
值的回调。当前的代码基本上一遍又一遍地调用handleScroll
和false
。
简而言之,您需要添加isHeaderMoved
作为效果的依赖项。您还应该在效果中移动handleScroll
侦听器,以便钩子eslint插件可以更正确地跟踪其依赖关系。
useEffect(
() => {
const handleScroll = () => {
if (window.pageYOffset > 0) {
if (!isHeaderMoved) {
setIsHeaderMoved(true)
}
} else if (isHeaderMoved) {
setIsHeaderMoved(false)
}
}
window.addEventListener("scroll", handleScroll)
return () => {
window.removeEventListener("scroll", handleScroll)
}
},
[isHeaderMoved],
)
请参阅Dan Abromov在该主题上的帖子中的这些部分(其中的示例可以比我更好地解释它)
如果有时间的话,有必要仔细阅读整个文章,以全面了解事物。
从skyboxer的评论中,我发现这也行得通,但是我将保留上述所有内容仅供参考。
useEffect(() => {
const handleScroll = () => {
setIsHeaderMoved(window.pageYOffset > 0)
}
window.addEventListener("scroll", handleScroll)
return () => {
window.removeEventListener("scroll", handleScroll)
}
}, [])
答案 1 :(得分:0)
这应该可行,您必须将window.pageYOffset
或isHeaderMoved
传递给useEffect
才能在每次更改时将其触发,如果您将其[]
留给它,会开火一次。
useEffect(
() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
},
[isHeaderMoved]
);
我认为您也可以使用useRef()
来做到这一点。
答案 2 :(得分:0)
我曾经遇到过同样烦人的问题
在父代码中创建组件时尝试在组件上添加一个key prop
<yourcomponent key="some_unique_value" />
这是因为在大多数情况下,特别是当您的组件被重用时,它通常可能仅在进行一些更改时重新渲染,而不是在您重用它时实际再次创建它,基于它的创建方式,因此 {{1 }} 不会被调用。例如在交换机、路由器、循环、条件...
所以添加一个密钥可以防止这种情况发生。如果是在循环中,则需要确保每个元素都是唯一的,如果找不到更好的唯一键,可以在键中包含索引 useEffect
。