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

React中如何给可点击图标绑定含setTimeout和clearTimeout的OnClick事件

核心问题

  1. clearTimeout用法错误:该API仅接收定时器ID作为唯一入参,不存在第二个时间参数,且你在创建定时器后立即执行清除操作,定时器逻辑永远不会触发
  2. 逻辑顺序颠倒:你需要的是点击瞬间触发背景高亮,再延迟恢复默认样式,现有代码是延迟设置高亮,和需求相反
  3. 定时器ID未持久化:函数组件每次渲染都会重建内部局部变量,存在临时变量里的定时器ID会丢失,无法跨渲染周期执行清除操作

修复代码

//rafce
import React, { useState, useRef, useEffect } from 'react';
// styled components
import styled from 'styled-components';
// icons
import { IoIosArrowUp, IoIosArrowDown } from 'react-icons/io';

const DurationIntervalComponent = () => {
  const [hours, setHours] = useState('0');
  const [showHoursArrows, setShowHourArrows] = useState(false);
  const [arrowActiveUp, setArrowActiveUp] = useState(false);
  const [arrowActiveDown, setArrowActiveDown] = useState(false);
  // 用ref持久化存储定时器ID
  const timerRef = useRef(null);

  // 组件卸载时清除残留定时器,避免内存泄漏
  useEffect(() => {
    return () => {
      if (timerRef.current) clearTimeout(timerRef.current);
    };
  }, []);

  const incrementHours = () => {
    // 先清除之前未执行的定时器,避免多次点击状态冲突
    if (timerRef.current) clearTimeout(timerRef.current);
    // 点击瞬间立刻设置激活态
    setArrowActiveUp(true);
    // 200ms后恢复默认样式,时长可自行调整
    timerRef.current = setTimeout(() => {
      setArrowActiveUp(false);
    }, 200);

    setHours((prevHours) => {
      if (!prevHours) return '0';
      if (+prevHours >= 24) return '0';
      return String(+prevHours + 1);
    });
  };

  const decrementHours = () => {
    if (timerRef.current) clearTimeout(timerRef.current);
    setArrowActiveDown(true);
    timerRef.current = setTimeout(() => {
      setArrowActiveDown(false);
    }, 200);

    setHours((prevHours) => {
      if (!prevHours) return '0';
      if (+prevHours <= 0) return '24';
      return String(+prevHours - 1);
    });
  };

  return (
    <Container>
      <Row>
        <p> Interval* </p>
        <Inputs>
          <Selection
            onMouseEnter={() => setShowHourArrows(true)}
            onMouseLeave={() => setShowHourArrows(false)}
          >
            {showHoursArrows && (
              <p
                className="icon"
                onClick={incrementHours}
                style={
                  arrowActiveUp
                    ? { backgroundColor: 'red' }
                    : { backgroundColor: 'none' }
                }
              >
                <IoIosArrowUp />
              </p>
            )}
            <SquareInput value={hours} />
            <p>hours</p>
            {showHoursArrows && (
              <p 
                className="icon" 
                onClick={decrementHours}
                style={
                  arrowActiveDown
                    ? { backgroundColor: 'red' }
                    : { backgroundColor: 'none' }
                }
              >
                <IoIosArrowDown />
              </p>
            )}
          </Selection>

          <div>
            <SquareInput />
            <p>minutes</p>
          </div>
        </Inputs>
      </Row>
      <hr />
      <Row>
        <p> Duration* </p>
        <Inputs>
          <SquareInput />
          <p>:</p>
          <SquareInput />
          <p>to</p>
          <SquareInput />
          <p>:</p>
          <SquareInput />
        </Inputs>
      </Row>
    </Container>
  );
};

const Container = styled.div`
  border: 1px solid #c5c5c5;
  border-radius: 15px;
`;
const Row = styled.div`
  display: flex;
  align-items: center;
  height: 150px;
  justify-content: space-between;
  padding: 20px;
`;

const Inputs = styled.div`
  display: flex;
  align-items: center;
  p {
    margin-right: 5px;
    font-size: 0.8em;
    text-align: center;
  }
`;

const Selection = styled.div`
  .icon {
    font-size: 1.2em;
    padding: 0;
    cursor: pointer;
  }
`;

const SquareInput = styled.input`
  width: 50px;
  height: 50px;
  border: 1px solid #c5c5c5;
  border-radius: 10px;
  outline: none;
  margin-right: 5px;
  font-size: 1.5em;
  text-align: center;
`;

export default DurationIntervalComponent;

补充说明

可以根据实际需求调整定时器的延迟时长,已额外给箭头添加了cursor: pointer样式优化交互体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 15:24:03