useCountDown (React Hooks)倒计时

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>
  );
}

演示:

倒计时发送验证码

注意点

  1. 闭包问题,需要使用setCount((count) => count - 1);函数式更新状态,使用ref获取最新count
  2. 计时器需要清理,避免内存泄漏
相关推荐
子兮曰10 小时前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰10 小时前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万10 小时前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝10 小时前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋11 小时前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁12 小时前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄12 小时前
JavaScript 隐式全局变量解析
javascript
汉堡大王952713 小时前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大14 小时前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师14 小时前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端