javascript
import { useState, useRef } from "react";
import "./styles.css";
/**********************************************************
* 补全 useCountDown (React Hooks)倒计时的功能
**********************************************************/
// 请补全,返回:
// count 当前剩余秒数
// start() 开始
// reset() 重置
// isRunning 是否在运行
function useCountDown(options) {
const {
total, // 总秒数
onEnd, // 倒计时结束回调
} = options;
const [count, setCount] = useState(total);
const countRef = useRef(total);
const [isRunning, setIsRunning] = useState(false);
const start = () => {
reset();
const updateCount = () => {
if (countRef.current <= 0) {
setIsRunning(false);
onEnd();
clearInterval(timer);
return;
}
setIsRunning(true);
setCount((count) => count - 1);
countRef.current--;
};
updateCount();
const timer = setInterval(() => {
updateCount();
}, 1000);
};
const reset = () => {
setCount(total);
countRef.current = total;
};
return {
count,
start,
isRunning,
};
}
// 使用示例
function SmsButton() {
const { count, start, isRunning } = useCountDown({
total: 6,
onEnd: () => console.log("可以重新发送了"),
});
return (
<button disabled={isRunning} onClick={start}>
{isRunning ? `${count}s 后重试` : "发送验证码"}
</button>
);
}
export default function App() {
return (
<div className="App">
<SmsButton />
</div>
);
}
演示:
倒计时发送验证码
注意点
- 闭包问题,需要使用
setCount((count) => count - 1);函数式更新状态,使用ref获取最新count值 - 计时器需要清理,避免内存泄漏