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

React自定义Hook实现鼠标滚轮滚动状态检测问题求助

解决方案:React自定义Hook检测鼠标滚动状态

原代码问题分析

你的实现思路方向正确,但存在两个关键问题:

  1. 组件卸载时未清理未执行的setTimeout,可能引发内存泄漏或无效状态更新
  2. 事件处理内的定时器管理不够严谨,容易出现状态不同步的情况

封装可复用自定义Hook useIsWheeling

下面是封装好的Hook,核心逻辑是滚动触发时立即返回true,滚动停止指定时长后切换为false,同时确保所有副作用在组件卸载时彻底清理:

import { useState, useEffect } from 'react';

function useIsWheeling(timeout = 300) {
  const [isWheeling, setIsWheeling] = useState(false);
  let scrollTimer = null;

  useEffect(() => {
    const handleWheel = () => {
      // 滚动触发时立刻将状态设为true
      setIsWheeling(true);
      // 清除之前的定时器,重置停止计时
      clearTimeout(scrollTimer);
      // 滚动停止timeout毫秒后,将状态切换为false
      scrollTimer = setTimeout(() => {
        setIsWheeling(false);
      }, timeout);
    };

    window.addEventListener('wheel', handleWheel);

    // 组件卸载时清理事件监听和定时器
    return () => {
      window.removeEventListener('wheel', handleWheel);
      clearTimeout(scrollTimer);
    };
  }, [timeout]);

  return isWheeling;
}

在组件中使用该Hook

替换你原来的逻辑,代码会更简洁可靠:

import { useRef, useEffect } from 'react';
import gsap from 'gsap';
import useIsWheeling from './useIsWheeling'; // 导入自定义Hook

function YourComponent() {
  const svgHeightRef = useRef(null);
  const isWheeling = useIsWheeling(300); // 可自定义延迟时长,默认300ms

  useEffect(() => {
    if (isWheeling) {
      gsap.to(svgHeightRef.current, {
        value: 200,
        duration: 0.5 
      });
    } else {
      gsap.to(svgHeightRef.current, {
        value: 500,
        duration: 1
      });
    }
  }, [isWheeling]);

  // 组件其他逻辑...
  return (
    {/* 你的JSX结构,示例引用svgHeightRef的元素 */}
    <svg height={svgHeightRef.current?.value || 500}>...</svg>
  );
}

关键优化说明

  • 内存泄漏防护:组件卸载时同时移除事件监听和清除定时器,避免无效的状态更新操作
  • 状态同步严谨:每次滚动事件触发都会重置定时器,确保只有在滚动完全停止后才切换状态
  • 复用性强:封装成Hook后,可在任意需要检测滚动状态的组件中直接调用

内容的提问来源于stack exchange,提问作者Reynald Lamury

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:17:20