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

React中onMouseUp触发clearInterval无法清除setInterval的问题

问题:React按钮按住启动定时器,松开后无法停止

我尝试实现按钮的onMouseDown事件,按住时启动定时器每隔1秒执行指定函数,松开按钮(onMouseUp)时清除定时器,但释放按钮后定时器仍持续运行。

当前代码:

import React from "react";

function PlantDefuser() {
    var interval

    function planting() {
        interval = setInterval(() => {
            console.log("Defuser Planted")
        }, 1000)
    }

    function notPlanting() {
        console.log(interval)
        clearInterval(interval)
    }

    return (
        <button onMouseDown={planting} onMouseUp={notPlanting}>Press and Hold</button>
    )
}

export default PlantDefuser
解决方案

问题根源是:函数组件每次渲染时,内部声明的var interval会被重新初始化,导致notPlanting中访问的interval可能不是planting中赋值的那个定时器引用,自然无法清除。

修复步骤:使用useRef保存定时器引用

React的useRef可以在组件多次渲染之间持久化保存同一个值,不会随渲染重置。修改后的代码如下:

import React, { useRef, useEffect } from "react";

function PlantDefuser() {
    const intervalRef = useRef(null);

    function planting() {
        // 先清除已存在的定时器,避免重复创建
        if (intervalRef.current) {
            clearInterval(intervalRef.current);
        }
        intervalRef.current = setInterval(() => {
            console.log("Defuser Planted");
        }, 1000);
    }

    function notPlanting() {
        if (intervalRef.current) {
            clearInterval(intervalRef.current);
            intervalRef.current = null; // 重置引用,避免无效值
        }
    }

    // 组件卸载时自动清除定时器,防止内存泄漏
    useEffect(() => {
        return notPlanting;
    }, []);

    return (
        <button onMouseDown={planting} onMouseUp={notPlanting}>Press and Hold</button>
    );
}

export default PlantDefuser;

核心改动说明:

  • 用useRef替代普通变量存储定时器ID,确保跨渲染周期引用一致
  • 在planting中先检查并清除旧定时器,避免多次触发onMouseDown创建多个定时器
  • notPlanting清除定时器后重置intervalRef.current,避免保留无效引用
  • 添加useEffect清理函数,组件卸载时自动清除定时器,防止内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 07:05:21