You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React实现滚动到底部递增计数器(上限4)的问题

解决滚动到底部递增计数器的问题

问题分析

你的代码存在两个核心问题:

  1. 依赖数组为空时,闭包捕获的fCount始终是初始值1,导致console.log(fCount)一直输出1,且滚动事件连续触发会多次执行状态更新;
  2. 将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 00:25:26