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.rhkb.cn/news/2814.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【编译构建】用cmake编译libjpeg动态库并实现转灰度图片

先编译出libjepg动态库 1、下载libjpeg源码: https://github.com/libjpeg-turbo/libjpeg-turbo 2、编译出动态库或静态库 写一个编译脚本&#xff0c;用cmake构建。 #!/bin/bash# 定义变量 SOURCE_DIR"/home/user/libjpeg-turbo-main" BUILD_DIR"${SOURCE_…

ORB-SLAM2源码学习: Frame.cc: cv::Mat Frame::UnprojectStereo将某个特征点反投影到三维世界坐标系中

前言 这个函数是在跟踪线程中更新上一帧的函数中被调用。 1.函数声明 cv::Mat Frame::UnprojectStereo(const int &i) 2.函数定义 1.获取这个特征点的深度值。 const float z mvDepth[i];深度值由双目或 RGB-D 传感器获取。 在双目情况下&#xff0c;这个深度来自…

单片机存储器和C程序编译过程

1、 单片机存储器 只读存储器不是并列关系&#xff0c;是从ROM发展到FLASH的过程 RAM ROM 随机存储器 只读存储器 CPU直接存储和访问 只读可访问不可写 临时存数据&#xff0c;存的是CPU正在使用的数据 永久存数据&#xff0c;存的是操作系统启动程序或指令 断电易失 …

【Excel】【VBA】双列排序:坐标从Y从大到小排列之后相同Y坐标的行再对X从小到大排列

Excel VBA 双列排序 功能概述 这段VBA代码实现了Excel中的双列排序功能&#xff0c;具体是&#xff1a; 跳过前3行表头先按C列数据从大到小排序在C列值相同的情况下&#xff0c;按B列从大到小排序排序时保持整行数据的完整性 流程图 #mermaid-svg-XJERemQluZlM4K8l {font-fa…

【25考研】西南交通大学软件工程复试攻略!

一、复试内容 复试对考生的既往学业情况、外语听说交流能力、专业素质和科研创新能力&#xff0c;以及综合素质和一贯表现等进行全面考查,主要考核内容包括思想政治素质和道德品质、外语听说能力、专业素质和能力&#xff0c;综合素质及能力。考核由上机考试和面试两部分组成&a…

运行fastGPT 第四步 配置ONE API 添加模型

上次已经装好了所有的依赖和程序。 下面在网页中配置One API &#xff0c;这个是大模型的接口。配置好了之后&#xff0c;就可以配置fastGPT了。 打开 OneAPI 页面 添加模型 这里要添加具体的付费模型的API接口填进来。 可以通过ip:3001访问OneAPI后台&#xff0c;**默认账号…

硬件知识:显示器发展历程介绍

目录 一、阴极射线管显示器(CRT) 二、等离子显示器(PDP) 三、液晶显示器(LCD) 四、传统LED显示器(LED) 五、有机发光二极管显示器(OLED) 六、量子点显示器(QD) 七、MiniLED显示器(MiniLED) 八、MicroLED显示器(MicroLED) 总结 显示器作为电子设备与人…

修复5.0.0r 64位版本浏览器和一些库找不到的问题

笔者在使用5.0.0r版本64位时踩过不少坑&#xff0c;先将相关修复方法分享 浏览器无法使用 base/startup/appspawn/appdata-sandbox64.json添加沙箱配置 相关修复pr:https://gitee.com/openharmony/startup_appspawn/pulls/1854/files {"src-path" : "/system…

【Flink系列】4. Flink运行时架构

4. Flink运行时架构 4.1 系统架构 Flink运行时架构——Standalone会话模式为例 1&#xff09;作业管理器&#xff08;JobManager&#xff09; JobManager是一个Flink集群中任务管理和调度的核心&#xff0c;是控制应用执行的主进程。也就是说&#xff0c;每个应用都应该被…

IP层之分片包的整合处理

前言 在上一章节中&#xff0c;笔者就IP层的接收代码逻辑做了简单介绍&#xff0c;并对实现代码进行了逻辑梳理以及仿真测试&#xff0c;并且在上一章节中&#xff0c;就IP层的分片包问题&#xff0c;如何确定分片包是否存在已经进行了简单介绍&#xff0c;并在接收模块中&…

使用jupyter notebook没有正常打开浏览器的几种情况解决

迅速记录前期 1.下载 https://www.anaconda.com/products/individual 2.安装 直接默认安装就行 3.打开jupyter notebook 在开始菜单里面可以找到 4.遇到的问题解决 1.运行jupyter notebook&#xff0c;黑窗口自动关了 每次黑窗口迅速的加载完就自己关掉了 也没有打开新…

50.【8】BUUCTF WEB HardSql

进入靶场 随便输输 上order by ????????&#xff0c;被过滤了,继续找其他也被过滤的关键字 #&#xff0c;-- -&#xff0c;-- 都不行&#xff0c;尝试其他特殊字符后发现and&#xff0c;union&#xff0c;select&#xff0c;空格&#xff0c;都被过滤了 如下 我就不知…

中国石油大学(华东)自动评教工具(涵盖爬虫的基础知识,适合练手)

我开发了一个用于自动评教的工具&#xff0c;大家可以试着用用&#xff0c;下面是链接。 https://github.com/restrain11/auto_teachingEvaluate 可以点个星吗&#xff0c;感谢&#xff01;&#x1fae1; 以下是我在开发过程中学到的知识 以及 碰到的部分问题 目录 动态爬虫和静…

深入云电脑PC Farm技术探讨,以阿里云、华为云、ToDesk为例

&#x1f31d;引言 近年来&#xff0c;云计算技术的飞速发展为各行各业的数字化转型带来了全新机遇&#xff0c;其中云电脑作为一种虚拟化桌面解决方案&#xff0c;逐渐成为个人用户与企业的核心选择。从远程办公、在线教育到高性能计算需求&#xff0c;云电脑通过为用户提供随…

RK3568平台(音频篇)lineout无声调试

一.声音硬件框架 硬件HP_MUTE已强制拉低。 二.设备树配置 es8388_sound: es8388-sound {status = "okay";compatible = "rockchip,multicodecs-card";rockchip,card-name = "rockchip-es8388";hp-det-gpio = <&gpio1 RK_PD2 GPIO_ACT…

docker 部署 MantisBT

1. docker 安装MantisBT docker pull vimagick/mantisbt:latest 2.先运行实例&#xff0c;复制配置文件 docker run -p 8084:80 --name mantisbt -d vimagick/mantisbt:latest 3. 复制所需要配置文件到本地路径 docker cp mantisbt:/var/www/html/config/config_inc.php.…

【Linux】Mysql部署步骤

一、JDK安装配置 在home目录下执行命令&#xff1a;mkdir Jdk 1.将JDK 上传至该文件夹&#xff0c;有些终端工具可以直接上传文件&#xff0c;比如&#xff1a;MobaXterm 可以看到安装包已经上传上来了 2.直接安装 命令&#xff1a;rpm -ivh jdk-8u311-linux-x64.rpm 3.安装成…

静态综合路由实验

实验拓扑 实验要求 1.除R5的环回地址外&#xff0c;整个其他所有网段基于192.168.1.0/24进行合理的IP地址划分 2.R1-R4每个路由器存在两个环回接口&#xff0c;用于模拟pc网段&#xff1b;地址也在192.168.1.0/24这个网络范围内 3.R1-R4上不能直接编写到达5.5.5.0/24的静态路由…

Unity ShaderGraph中Lit转换成URP的LitShader

ShaderGraph中的LitShader如下&#xff1a; 在顶点和片元着色器暴露出了上图中的几个参数&#xff0c;要转换成URPLitShaderLab,首先要找到这几个参数&#xff0c;打开LitShader&#xff0c;找到第一个Pass&#xff0c;可以看到下图中的顶点和片元的定义函数&#xff0c;还有引…

从漏洞管理到暴露管理:网络安全的新方向

在网络安全的快速发展中&#xff0c;传统的漏洞管理仍然是防御体系的基石。然而&#xff0c;面对日益复杂的威胁和不断增长的漏洞数量&#xff0c;单靠漏洞优先级评分&#xff08;如VPR&#xff09;已经无法满足现代安全需求。暴露管理这一全新的思维模式正在引领企业从被动应对…