当前位置: 首页 > article >正文

React封装倒计时按钮

背景

在开发过程中,经常需要使用到倒计时的场景,当用户点击后,按钮进行倒计时,然后等待邮件或者短信发送,每次都写重复代码,会让代码显得臃肿,所以封装一个组件来减少耦合

创建一个倒计时组件

在这里插入图片描述

编辑基本框架

设计3个参数,一个是倒计时时长,一个是开始时执行的方法,一个是展示文本

import React, { useState, useEffect, useRef } from 'react';
import { Button } from 'antd';

// 定义 CountdownButton 的属性接口
interface CountdownButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'> {
    countdownTime?: number;
    text?: string;
    onStart?: () => void;
}

const CountdownButton: React.FC<CountdownButtonProps> = ({ countdownTime = 60, text = '获取验证码', onStart, ...restProps }) => {
    const [isDisabled, setIsDisabled] = useState(false);
    const [buttonText, setButtonText] = useState(text);

    // 使用useRef来保存倒计时的当前值,避免状态重置
    const countdownRef = useRef(countdownTime);

    const intervalRef = useRef<number | null>(null);

    return (
        <Button >
            {buttonText}
        </Button>
    );
};

export default CountdownButton;

实现倒计时方法

实现剩余时间修改方法

    // 使用自定义的setCountdownRef函数来更新倒计时值
    const setCountdownRef = (update: (current: number) => number) => {
        const newCountdown = update(countdownRef.current);
        countdownRef.current = newCountdown;
    };

实现开启倒计时方法

   const handleStartCountdown = () => {

        // 立即更新按钮文本和状态
        setButtonText(`${countdownRef.current}s后重试`);
        setIsDisabled(true);
        if (typeof onStart === 'function') {
            onStart();
        }
        // 如果已经有定时器存在,则清除它
        if (intervalRef.current !== null) {
            clearInterval(intervalRef.current!);
        }

        intervalRef.current = setInterval(() => {
            setButtonText(`${countdownRef.current}s后重试`);
            setCountdownRef((prevCountdown) => {
                if (prevCountdown <= 1) {
                    clearInterval(intervalRef.current!);
                    intervalRef.current = null;
                    setButtonText(text);
                    setIsDisabled(false);
                    return countdownTime; // 重置倒计时时间
                }
                return prevCountdown - 1;
            });
        }, 1000);

实现清楚定时器方法

    // 清除定时器
    useEffect(() => {
        return () => {
            if (intervalRef.current !== null) {
                clearInterval(intervalRef.current!);
            }
        };
    }, []);

完整代码

import React, { useState, useEffect, useRef } from 'react';
import { Button } from 'antd';

// 定义 CountdownButton 的属性接口
interface CountdownButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'onClick'> {
    countdownTime?: number;
    text?: string;
    onStart?: () => void;
}

const CountdownButton: React.FC<CountdownButtonProps> = ({ countdownTime = 60, text = '获取验证码', onStart, ...restProps }) => {
    const [isDisabled, setIsDisabled] = useState(false);
    const [buttonText, setButtonText] = useState(text);

    // 使用useRef来保存倒计时的当前值,避免状态重置
    const countdownRef = useRef(countdownTime);

    const intervalRef = useRef<number | null>(null);

    // 清除定时器
    useEffect(() => {
        return () => {
            if (intervalRef.current !== null) {
                clearInterval(intervalRef.current!);
            }
        };
    }, []);

    const handleStartCountdown = () => {

        // 立即更新按钮文本和状态
        setButtonText(`${countdownRef.current}s后重试`);
        setIsDisabled(true);
        if (typeof onStart === 'function') {
            onStart();
        }
        // 如果已经有定时器存在,则清除它
        if (intervalRef.current !== null) {
            clearInterval(intervalRef.current!);
        }

        intervalRef.current = setInterval(() => {
            setButtonText(`${countdownRef.current}s后重试`);
            setCountdownRef((prevCountdown) => {
                if (prevCountdown <= 1) {
                    clearInterval(intervalRef.current!);
                    intervalRef.current = null;
                    setButtonText(text);
                    setIsDisabled(false);
                    return countdownTime; // 重置倒计时时间
                }
                return prevCountdown - 1;
            });
        }, 1000);

        // 立即减少一次倒计时,使首次显示正确的剩余时间
        setCountdownRef((prevCountdown) => prevCountdown - 1);
    };

    // 使用自定义的setCountdownRef函数来更新倒计时值
    const setCountdownRef = (update: (current: number) => number) => {
        const newCountdown = update(countdownRef.current);
        countdownRef.current = newCountdown;
    };

    return (
        <Button {...restProps} onClick={handleStartCountdown} disabled={isDisabled}>
            {buttonText}
        </Button>
    );
};

export default CountdownButton;

使用方法

<CountdownButton countdownTime={60} text={"获取验证码"} onStart={sendMsg} type="primary" />

效果

在这里插入图片描述


http://www.kler.cn/a/506101.html

相关文章:

  • 【25考研】西南交通大学软件工程复试攻略!
  • npm发布组件(vue3+webpack)
  • 【NLP】语言模型的发展历程 (1)
  • Kylin Linux V10 替换安装源,并在服务器上启用 EPEL 仓库
  • ubuntu支持中文的字体
  • SK海力士(SK Hynix)是全球领先的半导体制造商之一,其在无锡的工厂主要生产DRAM和NAND闪存等存储器产品。
  • msck批量
  • 案例|富唯智能复合机器人CNC柔性上下料
  • Python|【Pytorch】基于小波时频图与SwinTransformer的轴承故障诊断研究
  • 【网络编程】基础知识
  • 仿infobip模板功能-可通过占位符配置模板内容
  • 关于在vue3中使用v-for动态ref并控制el-tooltips当文字溢出时才展示的问题
  • WPS计算机二级•常用图表制作
  • NLP DAY1: 文本数据读取
  • 【优选算法】三数之和(双指针算法)
  • 【云岚到家】-day02-客户管理-认证授权
  • 如何在vue中渲染markdown内容?
  • 如何清理docker垃圾
  • Spring boot面试题----Spring Boot如何实现应用程序的热部署
  • 蓝桥杯备考:二叉树详解
  • STL中的List
  • 机器学习(一)
  • 基础vue3前端登陆注册界面以及主页面设计
  • centos 7 NFS部署
  • 计算机网络的五层协议
  • 【EI 会议征稿通知】第七届机器人与智能制造技术国际会议 (ISRIMT 2025)