React Hooks开箱即用的倒计时组件(验证码)

1,454 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

前言

这里提供的有TS/JS两种是已经封装好了倒计时验证码组件,直接copy就可以使用

JS

验证码组件

/* eslint-disable react-hooks/rules-of-hooks */
import { useState, useEffect, useRef } from 'react'

export const useCount = () => {
   var timeref = useRef(null)
   const [count, useCount] = useState(0)
   const [flag, useFlag] = useState(true) //处理节流
   const [timeText, usetext] = useState('获取验证码')
   useEffect(() => {
       return () => { clearInterval(timeref.current) } //清除
   }, [])
   useEffect(() => {
       if (count === 0) {
           useFlag(true) //当定时器结束的时候开启阀门
           clearInterval(timeref.current)
           usetext('获取验证码')
       } else {
           usetext(count + 's后获取验证码')
       }
   }, [count])
   let start = (num = 5) => {
       useFlag(!flag) // 如果是true 进入程序 改成false 关闭阀门
       if (!flag) return clearInterval(timeref.current) //如果是false 直接关闭 否则 开启阀门
       useCount(count=>count || num)
           timeref.current = setInterval(() => {
               useCount((count) => count - 1)
           }, 1000)
   }

   return { start, count, timeText }
}

在使用的组件内调用

import React from 'react'
import { useCount } from './useCount'
export default function Timer() {
    const { count, start, timeText } = useCount()
    return (
        <div>Timer ==== {count}
            <button onClick={() => {
               start()
            }}
            // disabled={!flag}
            >{timeText}</button>
        </div>
    )
}

以上具有暂停功能 如果不需要这个功能可以自行将开关代码注释

TS

以下代码没有具备暂停功能,如有需要自行添加

封装的组件

import { useEffect, useRef, useState } from 'react'
export default function useCountDown(initCount=10,callBack=()=>{}){
    const timeId = useRef<{id:number}>({ id: 0 })
    const [count, setCount] = useState(initCount)
    const start =()=>{
        setCount(initCount)
        timeId.current.id=window.setInterval(()=>{
            setCount((count)=>count-1)
        },1000)
    }
    useEffect(()=>
    window.clearInterval(timeId.current.id)
    ,[])
    useEffect(()=>{
      if(count===0){
          clearInterval(timeId.current.id)
          callBack()
      }
    },[callBack, count])
    return {start,count}
}

在使用的地方调用时 引入

 const {start, count} =useCountDown(5,()=>setSentable(true))

与JS封装不一样 在使用时 我们需要在调用的组件中定义一个开关

  const [sendable, setSentable] = useState(true)

当点击发送验证码时

  setSentable(false) /// 把sendable改为false
  start() // 开启定时器

按钮处理

onClick={sendable?sendCode:()=>{}} //判断sendable是否为true进行控制能否点击按钮

文字动态变化

{sendable?'发送验证码':count+'后获取'}

根据以上操作可以一步到位完成JS和TS的计时验证码