我想跟踪用户是在页面顶部还是向下滚动以相应地更改标题。这是我的代码。
const [isTop, changeIsTop] = useState(true)
useEffect(() => {
const handleScroll = () => {
changeIsTop(window.scrollY < 100)
}
window.addEventListener("scroll", handleScroll)
return () => {
window.removeEventListener("scroll", handleScroll)
}
}, [])
changeisTop
不执行任何操作。 isTop
始终设置为其初始值。知道为什么会这样吗?
答案 0 :(得分:2)
您的代码可以正常工作。您正在以正确的方式设置事件监听器。
useEffect(() =>{
const listener = () => {}
window.addEventListener('click', listener)
return () => window.removeEventListener('click', listener)
},[])
此效果将仅在组件的首次挂载(相当于componentDidMount
)中运行。装入组件后,侦听器将附加到全局click
事件,并且每次发生click
时都会调用listener
。您的问题是在哪里印刷价值。请记住,useEffect
只会运行一次,因此,如果您在console.log
内useEffect
会看到它的初始值(在附加listener
之前)。
useEffect(() =>{
const listener = () => {}
window.addEventListener('click', listener)
console.log('only run once')
return () => window.removeEventListener('click', listener)
},[])
要正确设置console.log
的值,请将其放在useEffect
之外
useEffect(() =>{
const listener = () => {}
window.addEventListener('click', listener)
return () => window.removeEventListener('click', listener)
},[])
console.log('run every render')
答案 1 :(得分:1)
您的代码应该可以正常运行(经过测试),我只建议在初始安装时仅一次注册您的回调:
const [isTop, changeIsTop] = useState(true);
const handleScroll = useCallback(() => {
changeIsTop(window.scrollY < 100)
}, []);
useEffect(() => {
window.addEventListener("scroll", handleScroll)
return () => { window.removeEventListener("scroll", handleScroll) }
}, [handleScroll])
但是为什么isTop的控制台日志总是在其中返回true。
您的初始isTop
值为true
。由于useEffect
是在initialMount上运行的,因此isTop
(即true
)将在handleScroll
回调中传递。每当检测到滚动时,将触发handleScroll
,但不会在组件上下文中触发,这意味着不会重新分配回调中的isTop
。
尝试设置
const [isTop, changeIsTop] = React.useState('bla');
,您会发现,如果您在console.log(isTop)
中handleScroll
,isTop
将是'bla'(永远为字符串!),但是在您的组件中它将被转换为{在第一个boolean
之后发生的{1}}。