React+Typescript implements countdown hook method

React+Typescript implements countdown hook method

First, setInterval is encapsulated as a Hook 👇

import { useEffect, useRef } from 'react'

/**
 * interTerval hooks component* @param fn execution function* @param delay time* @param options immediate When true, execute the fn function immediately and then execute the timer*/
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

Implementing the Countdown Hook

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

interface ITime {
  /** Current time */
  currentTime?: number
  /** End time */
  endTime?: number
  /** Another way, instead of passing the current time and end time, directly pass the time difference*/
  differTime?: number
}

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

/**
 * Countdown hooks
 * @param options time object* @param cb callback function executed when countdown is completed* @param noImmediate whether to execute the callback immediately when the time passed in meets the callback execution conditions, the default is false*/
function useCountDown(
  options: ITime,
  cb?: () => void,
  noImmediate?: boolean
): ICbTime {
  const { currentTime = 0, endTime = 0, differTime = 0 } = options
  const [diffTime, setDiffTime] = useState(0)
  /** The time when the component receives the parameter*/
  const entryTime = useRef<number>(0)
  /** The time difference required by the current countdown*/
  const maxTime = useRef<number>(0)
  /** Is it possible to execute callback? */
  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 is used to solve the react error problem:
       * 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

Write a demo to see the effect👇

  const TimeArea = () => {
    const { d, h, m, s } = useCountDown(
      {
        currentTime: 1631262176333,
        endTime: 1831062176333
      },
      () => {
        alert('Countdown ends')
      }
    )
    return (
      <div style={{ width: '200px', height: '200px' }}>
        {d} days until task end<i>{h < 10 ? '0' + h : h}</i>:
        <i>{m < 10 ? '0' + m : m}</i>:<i>{s < 10 ? '0' + s : s}</i>
      </div>
    )
  }

This is the end of this article about how to implement countdown hook with React+Typescript. For more relevant content about countdown with React+Typescript, please search previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • React countdown function implementation code - decoupling general
  • Realize countdown effect based on vue and react
  • Example code for implementing a countdown using react render props
  • Implementation of React registration countdown function
  • React Native verification code countdown tool sharing

<<:  Summary of MySQL database usage specifications

>>:  Detailed tutorial on installing CUDA9.0 on Ubuntu16.04

Recommend

HTML left, center, right adaptive layout (using calc css expression)

In the latest HTML standard, there is a calc CSS e...

Vue+js realizes video fade-in and fade-out effect

Vue+js realizes the fade in and fade out of the v...

Introduction to CSS style classification (basic knowledge)

Classification of CSS styles 1. Internal style --...

Recommend 60 paging cases and good practices

<br />Structure and hierarchy reduce complex...

Zen coding resource update function enhancement

Official website: http://code.google.com/p/zen-cod...

A brief discussion on order reconstruction: MySQL sharding

Table of contents 1. Objectives 2. Environmental ...

How to view the execution time of SQL statements in MySQL

Table of contents 1. Initial SQL Preparation 2. M...

In-depth analysis of the slow query problem of MySQL Sending data

Through an example, I shared with you the solutio...

Simple implementation of vue drag and drop

This article mainly introduces the simple impleme...

Solution to Linux QT Kit missing and Version empty problem

Currently encountering such a problem My situatio...

Examples of using HTML list tags dl, ul, ol

Copy code The code is as follows: <!-- List ta...

mysql5.7.21.zip installation tutorial

The detailed installation process of mysql5.7.21 ...