React用30多行代码实现时间倒计时组件

319 阅读2分钟

最近有个需求,需要在页面展示时间的倒计时。上网搜了一下,没找到单个合适的小组件,于是想着自己写一个。

先捋下大概思路:

  1. 组件中需要有一个时间,这个时间需要与当前的日期进行差值计算,算出来后,判断还剩多长时间;
  2. 启用定时器,每1秒将差值时间-1
  3. 将差值时间以「时:分:秒」的格式显示
  4. 倒计时结束后,执行回调函数

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>
);

效果

image.png

使用时的坑

如果是在nextjs的项目中使用这个组件,可能遇到以下问题

nextjs 14+

image.png

解决方法:使用use client

image.png

解决方法:动态导入

import dynamic from "next/dynamic"
const DateCountDown = dynamic(() => (import('./components/DateCountDown')), { ssr: false })

nextjs12

nextjs12可能会出现图二的报错,那么直接使用动态导入的方法就可以

总结

后期可以在这个基础上实现天/时/分/秒的倒计时