最近看到一个面试题,如何使用React Hooks封装一个短信倒计时。以下是代码片段
import { Button } from "antd";
import { useCountDown } from "./useCountDown.tsx";
export default function App() {
const [time, startTime, canEdit, text] = useCountDown(5, "获取验证码");
return (
<div className="App">
<Button onClick={startTime} type="primary" disabled={!canEdit}>
{text}
</Button>
</div>
);
}
import { useEffect, useRef, useState } from "react";
export const useCountDown = (initTime: number, initText: string) => {
const [time, setTime] = useState(initTime);
const [canEdit, setCanEdit] = useState(true);
const [text, setText] = useState(initText);
const timerRef: any = useRef();
useEffect(() => {
if (time < 0) {
clearInterval(timerRef.current);
setCanEdit(true);
setText(initText);
} else {
if (time < initTime) {
setText(`重新获取(${time}s)`);
}
}
}, [time]);
useEffect(() => {
// 在组件销毁的时候需要清除定时器
// 如果在上面的useEffect清除的话,那么在commit阶段中的mutation子阶段便会调用return 的回调方法清除定时器
return () => {
clearInterval(timerRef.current);
};
}, []);
const startTime = () => {
setCanEdit(false);
setText(`重新获取(${time}s)`);
if (!timerRef.current) {
timerRef.current = setInterval(() => {
setTime((t) => t - 1);
}, 1000);
}
};
return [time, startTime, canEdit, text];
};