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
In the latest HTML standard, there is a calc CSS e...
Vue+js realizes the fade in and fade out of the v...
Installation introduction under Windows: Check ou...
Classification of CSS styles 1. Internal style --...
Whether the a tag opens a new page: (1) Baidu Ency...
The reason is this I wanted to deploy a mocker pl...
<br />Structure and hierarchy reduce complex...
Official website: http://code.google.com/p/zen-cod...
Table of contents 1. Objectives 2. Environmental ...
Table of contents 1. Initial SQL Preparation 2. M...
Through an example, I shared with you the solutio...
This article mainly introduces the simple impleme...
Currently encountering such a problem My situatio...
Copy code The code is as follows: <!-- List ta...
The detailed installation process of mysql5.7.21 ...