React如何限制函数短时间内被频繁调用
实现函数的2秒节流限制(立即执行版)
你需要的是**节流(Throttle)**机制——允许函数立即执行一次,之后在指定时间内(这里是2秒)无法再次触发,正好匹配你防止短时间内多次调用setNextPage/setPrevPage的需求。
方式一:直接在事件处理中添加时间判断(简单直观)
在组件中通过useRef存储两个分页函数的上次调用时间戳(useRef的值不会随组件渲染重置,适合跨渲染周期保存状态),每次触发时检查时间间隔是否满足要求:
import { useRef, useState } from 'react'; // 组件内部 const calendarContainerRef = useRef<HTMLDivElement>(null); const [dragMode, setDragMode] = useState(true); // 假设dragMode是组件状态 // 记录上次调用时间的ref const lastNextCall = useRef<number>(0); const lastPrevCall = useRef<number>(0); const THROTTLE_DELAY = 2000; // 2秒限制 const handleMouseMove = (event: React.MouseEvent) => { if (dragMode) { setDragMode(false); const bounds = event.currentTarget.getBoundingClientRect(); const xPosition = event.clientX - bounds.left; const now = Date.now(); // 处理setNextPage的节流 if (xPosition > (calendarContainerRef.current?.clientWidth || 0) - 20) { if (now - lastNextCall.current >= THROTTLE_DELAY) { setNextPage(); lastNextCall.current = now; // 更新上次调用时间 } } // 处理setPrevPage的节流 if (xPosition < 90) { if (now - lastPrevCall.current >= THROTTLE_DELAY) { setPrevPage(); lastPrevCall.current = now; // 更新上次调用时间 } } } }; return ( <Scheduler onMouseMove={handleMouseMove} /> );
方式二:封装通用节流Hook(复用性强)
如果需要在多个地方使用节流逻辑,可以封装一个通用的useThrottle Hook,简化代码:
import { useRef, useCallback } from 'react'; // 通用节流Hook const useThrottle = (fn: () => void, delay: number) => { const lastCall = useRef(0); return useCallback(() => { const now = Date.now(); if (now - lastCall.current >= delay) { fn(); lastCall.current = now; } }, [fn, delay]); }; // 组件内部使用 const throttledNextPage = useThrottle(setNextPage, 2000); const throttledPrevPage = useThrottle(setPrevPage, 2000); const handleMouseMove = (event: React.MouseEvent) => { if (dragMode) { setDragMode(false); const bounds = event.currentTarget.getBoundingClientRect(); const xPosition = event.clientX - bounds.left; if (xPosition > (calendarContainerRef.current?.clientWidth || 0) - 20) { throttledNextPage(); // 直接调用节流后的函数 } if (xPosition < 90) { throttledPrevPage(); // 直接调用节流后的函数 } } };
关键说明:
- 两种方式都保证了函数立即执行第一次调用,之后必须等待2秒才能再次触发。
useRef用于存储时间戳,避免组件渲染时重置状态。- 方式二的
useCallback确保节流函数不会随组件渲染频繁重建,优化性能。
内容的提问来源于stack exchange,提问作者Matexon
相关产品推荐
相关产品推荐

