最近有个需求,需要在页面展示时间的倒计时。上网搜了一下,没找到单个合适的小组件,于是想着自己写一个。
先捋下大概思路:
- 组件中需要有一个时间,这个时间需要与当前的日期进行差值计算,算出来后,判断还剩多长时间;
- 启用定时器,每1秒将差值时间-1
- 将差值时间以「时:分:秒」的格式显示
- 倒计时结束后,执行回调函数
coding
根据以上思路,编写代码
import React, { useState, useEffect } from 'react'
const DateCountDown = ({ date, style = {}, onFinish }) => {
const temp = Math.floor((date - new Date().getTime()) / 1000)
const [time, setTime] = useState(temp)
useEffect(() => {
const interval = setInterval(() => {
setTime(prevTime => {
if (prevTime === 0) {
clearInterval(interval)
return prevTime
} else {
return prevTime - 1
}
})
}, 1000)
return () => clearInterval(interval)
}, [])
const formatTime = time => {
const hours = String(Math.floor(time / 3600)).padStart(2, '0')
const minutes = String(Math.floor((time % 3600) / 60)).padStart(2, '0')
const seconds = String(time % 60).padStart(2, '0')
return `${hours}:${minutes}:${seconds}`
}
const handleFinish = () => {
onFinish && onFinish()
return "00:00:00"
}
return (
<p style={style}>
<span>{time > 0 ? formatTime(time) : handleFinish()}</span>
</p>
)
}
export default DateCountDown
使用说明
- 传入的date需要是时间戳格式,默认是ms
- 可以自定义样式
- 回调函数
测试
import React from "react";
import ReactDOM from "react-dom/client";
import DateCountDown from "./components/index.js"
export default function App() {
const time = new Date().getTime() + 100000
return (
<div>
<h3>时间倒计时</h3>
<DateCountDown date={time} style={{
fontSize:'36px',
fontBold:'weight',
color:'#f00'
}}
onFinish={()=>'倒计时结束啦!'}/>
</div>
)
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
效果
使用时的坑
如果是在nextjs的项目中使用这个组件,可能遇到以下问题
nextjs 14+
解决方法:使用use client
解决方法:动态导入
import dynamic from "next/dynamic"
const DateCountDown = dynamic(() => (import('./components/DateCountDown')), { ssr: false })
nextjs12
nextjs12可能会出现图二的报错,那么直接使用动态导入的方法就可以
总结
后期可以在这个基础上实现天/时/分/秒的倒计时