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:
|
<<: Summary of MySQL database usage specifications
>>: Detailed tutorial on installing CUDA9.0 on Ubuntu16.04
The <label> tag defines a label (tag) for an...
Table of contents 1. Cross-domain filter CorsFilt...
ffmpeg is a very powerful audio and video process...
Table of contents 1. v-bind: can bind some data t...
emmm the name is just a random guess 2333 Preface...
Preface I had previously enabled Docker's 237...
Scenario: When page A opens page B, after operati...
Download Nginx image in Docker docker pull nginx ...
closure service nginx stop systemctl stop nginx s...
Table of contents 1. Overview 2. nginx.conf 1) Co...
Specific method: 1. Open Command Prompt 2. Enter ...
Table of contents Data Brokers and Events Review ...
This article example shares the specific code of ...
Everyone has played the pinball and brick-breakin...
How to install flash in Linux 1. Visit the flash ...