React实现滚动到底部递增计数器(上限4)的问题
解决滚动到底部递增计数器的问题
问题分析
你的代码存在两个核心问题:
- 依赖数组为空时,闭包捕获的
fCount始终是初始值1,导致console.log(fCount)一直输出1,且滚动事件连续触发会多次执行状态更新; - 将
fCount加入依赖数组后,每次计数变化都会重新绑定滚动事件,多个监听同时生效,导致日志输出混乱。
解决方案
使用useRef标记是否已触发过当前滚动周期的计数更新,同时正确清理事件监听,确保每次滚动到底部仅触发一次计数递增,直到达到上限4:
import { useState, useEffect, useRef } from 'react'; function YourComponent() { const [fCount, setFCount] = useState(1); // 标记当前滚动周期是否已触发过计数更新 const isTriggered = useRef(false); useEffect(() => { const handleScroll = () => { const isAtBottom = window.innerHeight + window.pageYOffset >= document.body.offsetHeight; // 仅在到达底部、计数未到上限且未触发过本次滚动时执行 if (isAtBottom && fCount < 4 && !isTriggered.current) { isTriggered.current = true; setFCount(prev => { const newCount = prev + 1; console.log(newCount); return newCount; }); } // 离开底部时重置标记,允许下次滚动触发 if (!isAtBottom) { isTriggered.current = false; } }; window.addEventListener('scroll', handleScroll); // 组件卸载或依赖变化时移除监听,避免内存泄漏和重复绑定 return () => window.removeEventListener('scroll', handleScroll); }, [fCount]); return <div>你的组件内容</div>; } export default YourComponent;
关键说明
useRef防重复触发:isTriggered用来避免同一滚动操作中多次执行计数更新,因为滚动事件会连续触发数十次,标记后仅执行一次,离开底部再重置;- 清理事件监听:useEffect的返回函数移除滚动监听,防止组件卸载后残留监听,也避免多次绑定导致的重复执行;
- 函数式状态更新:
setFCount使用函数式写法,确保拿到最新的状态值,避免闭包导致的状态滞后; - 上限控制:判断条件
fCount < 4确保计数器最终停在4(初始1,递增3次后到4)。
内容的提问来源于stack exchange,提问作者JoeBarbaro
相关产品推荐
相关产品推荐

