React+Typescript实现倒计时Hook的方法

首先对setInterval做了Hook化封装👇

import { useEffect, useRef } from 'react'

/**
 * interTerval hooks组件
 * @param fn 执行函数
 * @param delay 时间
 * @param options immediate为true时,先立即执行一次fn函数后再执行定时器
 */
function useInterval(
  fn: () => void,
  delay: number | null | undefined,
  options?: {
    immediate?: boolean
  }
): void {
  const immediate = options?.immediate
  const timerRef = useRef<() => void>()

  timerRef.current = fn

  useEffect(() => {
    if (delay === undefined || delay === null) {
      return
    }
    if (immediate) {
      timerRef.current?.()
    }
    const timer = setInterval(() => {
      timerRef.current?.()
    }, delay)
    return () => {
      clearInterval(timer)
    }
  }, [delay])
}

export default useInterval

实现倒计时Hook

import { useState, useEffect, useRef, useMemo } from 'react'
import { useInterval } from './'

interface ITime {
  /** 当前时间 */
  currentTime?: number
  /** 结束时间 */
  endTime?: number
  /** 另一种方式,不传当前时间和结束时间,直接传时间差 */
  differTime?: number
}

interface ICbTime {
  d: number
  h: number
  m: number
  s: number
}

/**
 * 倒计时hooks
 * @param options 时间对象
 * @param cb 倒计时完成时执行的回调函数
 * @param noImmediate 时间传进来满足执行回调条件时,是否立即执行回调,默认false执行
 */
function useCountDown(
  options: ITime,
  cb?: () => void,
  noImmediate?: boolean
): ICbTime {
  const { currentTime = 0, endTime = 0, differTime = 0 } = options
  const [diffTime, setDiffTime] = useState(0)
  /** 组件接收到参数时的时间 */
  const entryTime = useRef<number>(0)
  /** 当前倒计时要求的时间差 */
  const maxTime = useRef<number>(0)
  /** 是否可以执行回调 */
  const isImplementCb = useRef(false)

  useEffect(() => {
    if (!isImplementCb.current) {
      isImplementCb.current = true
    }
    if ((currentTime > 0 && endTime > 0) || differTime > 0) {
      entryTime.current = new Date().getTime()
      maxTime.current = differTime > 0 ? differTime : endTime - currentTime
      if (maxTime.current <= 0 && noImmediate) {
        isImplementCb.current = false
      }
      setDiffTime(maxTime.current)
    }
  }, [currentTime, endTime, differTime])

  useInterval(
    () => {
      const curtTimes = new Date().getTime()
      const TimeDifference = curtTimes - entryTime.current
      setDiffTime(maxTime.current - TimeDifference)
    },
    diffTime <= 0 ? null : 1000
  )

  const timeObj = useMemo(() => {
    const time = diffTime > 0 ? diffTime / 1000 : 0
    const d = Math.floor(time / (24 * 60 * 60))
    const h = Math.floor((time / (60 * 60)) % 24)
    const m = Math.floor((time / 60) % 60)
    const s = Math.ceil(time % 60)

    if (diffTime <= 0 && isImplementCb.current) {
      /**
       * setTimeout用于解决react报错问题:
       * annot update during an existing state transition (such as within `render`).
       * Render methods should be a pure function of props and state.
       */
      setTimeout(() => {
        cb?.()
      }, 0)
    }
    return { d, h, m, s }
  }, [diffTime])

  return timeObj || ({} as ICbTime)
}

export default useCountDown

写个demo看一下效果👇

  const TimeArea = () => {
    const { d, h, m, s } = useCountDown(
      {
        currentTime: 1631262176333,
        endTime: 1831062176333
      },
      () => {
        alert('倒计时结束')
      }
    )
    return (
      <div style={{ width: '200px', height: '200px' }}>
        距离任务结束 {d}天<i>{h < 10 ? '0' + h : h}</i>:
        <i>{m < 10 ? '0' + m : m}</i>:<i>{s < 10 ? '0' + s : s}</i>
      </div>
    )
  }

到此这篇关于React+Typescript实现倒计时Hook的方法的文章就介绍到这了,更多相关React+Typescript实现倒计时 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2021-09-13

React注册倒计时功能的实现

一.React版本 16.4.1 二.具体代码如下 设置state属性 constructor(props){ super(props); this.state = { btnText:'获取验证码', seconds: 60, //称数初始化 liked: true //获取验证码文案 } } 2.倒计时 // 获取验证码 sendCode = () => { let siv = setInterval(() => { this.setState({ liked:false, seconds

React倒计时功能实现代码——解耦通用

需求分析 需求 在某个页面中需要有一个倒计时的功能,倒计时 5 s,5s钟后跳转到新的界面 分析 首先是实现倒计时功能 其次是实现在每倒计时 1 s后页面上要执行 倒计时秒数变化的功能 最后是实现倒计时完成后 跳转到指定页面的功能 初版做法 代码 let waitTime = 5 class DemoPage extends React.Component { constructor(props) { super(props); this.state = { time: '', }; } com

使用react render props实现倒计时的示例代码

react的组件模式可以观看Michael Chan的演讲视频,平时大家常听到的react模式也是HOC, HOC的使用场景很多,譬如react-redux的connect,这里不赘述HOC相关,感兴趣可以自行了解. 首先是这样一个场景,我的业务需要实现倒计时,倒计时你懂得,倒计时经常应用在预告一个活动的开始,像秒杀,像开售抢购等,或者活动的截止. 我们来梳理一下这个倒计时的功能: 定时更新时间,以秒为度; 可以更新倒计时的截止时间,比如从10月1日更新为10月2日: 倒计时结束,执行对应结束逻

React Native验证码倒计时工具类分享

本文实例为大家分享了React Native验证码倒计时工具类的具体代码,供大家参考,具体内容如下 因为以前直接用定时器,没去计算当前的时候,每次退出程序的时候,定时器一直不走,这个工具类简单的解决程序退出后台,定时器不走的bug,那么,直接上代码咯~~ /** * Created by zhuang.haipeng on 2017.9.11 * * 广告倒计时,验证码倒计时工具类 * * 用法: //60 * 1000 为60秒 , 60 * 60 * 100 为60分钟 ... * let

基于vue、react实现倒计时效果

本文实例为大家分享了基于vue.react实现倒计时效果的具体代码,供大家参考,具体内容如下 Vue 方案一:俩个元素 HTML: <div id="example"> <button @click="send"> <span v-if="sendMsgDisabled">{{time+'秒后获取'}}</span> <span v-if="!sendMsgDisabled"

jQuery基于扩展实现的倒计时效果

本文实例讲述了jQuery基于扩展实现的倒计时效果.分享给大家供大家参考,具体如下: <div id="fnTimeCountDown" data-end=""> <span class="mini">00</span>分 <span class="sec">00</span>秒 <span class="hm">000</spa

基于vue.js无缝滚动效果

一个简单的基于vue.js的无缝滚动 :feet:在线文档demo :ear_of_rice:小demo :blue_book:English Document 安装 NPM npm install vue-seamless-scroll --save 使用 ES6 详情的demo页面 example-src/App.vue // **main.js** import Vue from 'vue' import scroll from 'vue-seamless-scroll' Vue.use(

基于Vue实现拖拽效果

效果图 demo1.gif 分清clientY pageY screenY layerY offsetY的区别 在我们想要做出拖拽这个效果的时候,我们需要分清这几个属性的区别,这几个属性都是计算鼠标点击的偏移值,我们需要对其进行了解才可以继续实现我们的拖拽效果 clientY 指的是距离可视页面左上角的距离 pageY 指的是距离可视页面左上角的距离(不受页面滚动影响) screenY 指的是距离屏幕左上角的距离 layerY 指的是找到它或它父级元素中最近具有定位的左上角距离 offsetY

基于JavaScript实现活动倒计时效果

本文实例为大家分享了js倒计时效果的具体代码,供大家参考,具体内容如下 <!DOCTYPE html> <html> <head> <title>countDown</title> <style type="text/css"> #mydiv{ width:150px; background-color:green; margin:0 auto; padding:0 auto; color:pink; } <

vue+moment实现倒计时效果

本文实例为大家分享了vue+moment实现倒计时的具体代码,供大家参考,具体内容如下 示例 代码 <!-- 使用计算属性,传入截止日期 --> <span>{{countDown(endDate)}}</span> /*引入日期插件*/ import moment from 'moment' export default { data() { return { now: moment(), endDate: '2019-05-07 08:20:00', } }, mo

详解基于Vue/React项目的移动端适配方案

前言 本文的目标是通过下文介绍的适配方案,使用vue或react开发移动端及H5的时候,不需要再关心移动设备的大小,只需要按照固定设计稿的px值布局,提升开发效率. 下文给出了本人分别使用create-react-app搭建的react(create-react-app)项目和使用vue-cli 2.x 搭建的vue项目中的 亲测可用 配置方案. px2rem或postcss-px2rem 在移动端中,为了设配不同的设备,通常使用rem来做适配. rem是通过根元素进行适配的,网页中的根元素指的

JS基于递归实现倒计时效果的方法

本文实例讲述了JS基于递归实现倒计时效果的方法.分享给大家供大家参考,具体如下: 效果: 事件: //发送验证码 $('.js-sms-code').click(function(){ $(this).attr("disabled", "disabled").html("<span style='color:#666'><span id='countdown'>60</span>s 后再试</span>&qu

基于Vue实现页面切换左右滑动效果

基于Vue的页面切换左右滑动效果,具体内容如下 HTML文本页面: <template> <div id="app> <transition :name="direction" mode="out-in"> <!--动态获得transition 的name值--> <router-view class="app-view" wechat-title></router-vi

C#基于TimeSpan实现倒计时效果的方法

本文实例展示了C#基于TimeSpan实现倒计时效果的方法,比较实用的功能,对于初学者来说有一定的学习参考价值.具体实现方法如下: 示例代码如下: using System; using System.Threading; namespace ConsoleApplication29 { class Program { static void Main(string[] args) { try { DateTime _timeEnd = DateTime.Now.AddSeconds(62);