使用React hooks封装倒计时组件

35 阅读1分钟

最近看到一个面试题,如何使用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];
};