React hook 中,使用setInterval定时器,制作时、分、秒倒计时功能

需求:后台返回截止日期时间戳,根据当前时间,页面回显精确到秒的倒计时。

思路: 抽一个countDown组件,传入截止时间timeStamp,使用setInterval进行倒计时,render页面。

遇到的问题: 在useEffect中,新值只变化一次,没有实时的倒计时。

参考文章: useEffect 完整指南

解决方案:

  1. 最开始将时分秒作为整体time返回,发现页面没有实时变化。然后将变化后的时间作为useEffcet的依赖,这样页面会动态显示倒计时,但是这样做会一直创建不同的setInterval,不推荐。

  2. 拆分声明时、分、秒,使用setState的函数形式更新值,只创建一个setInterval。

组件代码如下:

import * as React from "react";
const { useState, useEffect, useRef } = React;

interface IProps {
    timeStamp: any;
}

const CountDown = (props: IProps) => {
    const { timeStamp } = props;
    const intervalRef = useRef<any>(null);

    const now: any = Math.round(new Date().getTime() / 1000).toString();  //获取当前时间
    const end: any = timeStamp;  //设置截止时间  

    const [leftTime, setLeftTime] = useState(end - now); //时间间隔
    const [h, setHours] = useState<any>("");   //小时
    const [m, setMinutes] = useState<any>("");  //分钟
    const [s, setSeconds] = useState<any>("");  //秒


    useEffect(() => {
        if (leftTime > 0) {
            intervalRef.current = setInterval(() => {
                const newNow: any = Math.round(new Date().getTime() / 1000).toString();  // 重新获取当前时间

                let newLeftTime = timeStamp - newNow
                setLeftTime(() => newLeftTime)  //计算新的时间间隔数值

                let hours = Math.floor(newLeftTime / 60 / 60 % 24) < 10 ? `0${Math.floor(newLeftTime / 60 / 60 % 24)}` : Math.floor(newLeftTime / 60 / 60 % 24);
                let minutes = Math.floor(newLeftTime / 60 % 60) < 10 ? `0${Math.floor(newLeftTime / 60 % 60)}` : Math.floor(newLeftTime / 60 % 60);
                let seconds = Math.floor(newLeftTime % 60) < 10 ? `0${Math.floor(newLeftTime % 60)}` : Math.floor(newLeftTime % 60);
                setHours(() => hours)  //函数写法 设置小时
                setMinutes(() => minutes)  //函数写法 设置分钟
                setSeconds(() => seconds)  //函数写法保证值在setInterval里更新,避免useEffect的bug

            }, 1000);
        } else {
            setLeftTime(0)
            setHours(0)
            setMinutes(0)
            setSeconds(0)
            clearInterval(intervalRef.current);
        }
        return () => clearInterval(intervalRef.current);   
    }, []);  //不传依赖


    return (
        <>
            { leftTime <= 0 && <span>-</span>}
            { leftTime > 0 && <span>{`${h}:${m}:${s}`}</span>}
        </>
    )

}

export default CountDown;

页面中使用

import CountDown from './countDown'
<CountDown timeStamp={text} />

暂时记录这些,欢迎指正!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值