import { useState, useEffect, useRef, useCallback } from 'react';
const useCountDown = (initialCount) => {
const [count, setCount] = useState(initialCount);
const [isRunning, setIsRunning] = useState(false);
const timerRef = useRef(null);
const clearTimer = useCallback(() => {
if (timerRef.current) {
clearInterval(timerRef.current);
timerRef.current = null;
}
}, []);
const start = useCallback(() => {
if (!isRunning && count > 0) {
setIsRunning(true);
// 先清除可能存在的旧定时器
clearTimer();
// 设置新定时器
timerRef.current = setInterval(() => {
setCount((prevCount) => {
if (prevCount <= 1) {
setIsRunning(false);
clearTimer(); // 倒计时结束,清理定时器
return 0;
}
return prevCount - 1;
});
}, 1000);
}
}, [isRunning, count, clearTimer]);
const pause = useCallback(() => {
setIsRunning(false);
clearTimer();
}, [clearTimer]);
const reset = useCallback((newCount) => {
setIsRunning(false);
clearTimer();
setCount(newCount !== undefined ? newCount : initialCount);
}, [initialCount, clearTimer]);
// 组件卸载时,务必清理定时器防止内存泄漏
useEffect(() => {
return clearTimer;
}, [clearTimer]);
return { count, isRunning, start, pause, reset };
};
export default useCountDown;
使用
import React from 'react';
import useCountDown from './useCountDown';
const VerificationCodeButton = () => {
const { count, isRunning, start } = useCountDown(60);
const handleSendCode = () => {
// 这里模拟发送验证码的请求
console.log('发送验证码...');
start(); // 开始倒计时
};
return (
<button onClick={handleSendCode} disabled={isRunning}>
{isRunning ? `剩余 ${count} 秒` : '获取验证码'}
</button>
);
};