返回

用hooks写一个倒计时方法

前端

认识hooks

在深入探讨倒计时实现之前,我们首先需要了解hooks。Hooks是React 16.8版本引入的一项重要特性,它允许我们在函数组件中使用状态和生命周期方法。这使得我们可以编写更简洁、更易于维护的代码。

第一种方法:使用两个useState,useEffect

最基本的方法是使用两个useState和一个useEffect。第一个useState用于存储当前的倒计时时间,第二个useState用于存储倒计时是否结束。useEffect用于在组件挂载时启动倒计时,并在每次更新时检查倒计时是否结束。

import { useState, useEffect } from "react";

const Countdown = ({ targetDate }) => {
  const [currentTime, setCurrentTime] = useState(new Date());
  const [isCountdownFinished, setIsCountdownFinished] = useState(false);

  useEffect(() => {
    const intervalId = setInterval(() => {
      const newCurrentTime = new Date();
      setCurrentTime(newCurrentTime);

      if (newCurrentTime >= targetDate) {
        clearInterval(intervalId);
        setIsCountdownFinished(true);
      }
    }, 1000);

    return () => clearInterval(intervalId);
  }, [targetDate]);

  if (isCountdownFinished) {
    return <p>倒计时结束!</p>;
  }

  const remainingTime = targetDate - currentTime;
  const days = Math.floor(remainingTime / (1000 * 60 * 60 * 24));
  const hours = Math.floor(
    (remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
  );
  const minutes = Math.floor((remainingTime % (1000 * 60 * 60)) / (1000 * 60));
  const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000);

  return (
    <p>
      距离{targetDate.toLocaleString()}还有:
      {days}天{hours}小时{minutes}分钟{seconds}秒
    </p>
  );
};

export default Countdown;

第二种方法:使用一个useState

第二种方法与第一种方法类似,但我们使用了一个useState来同时存储当前时间和倒计时是否结束的状态。这使得代码更加简洁。

import { useState, useEffect } from "react";

const Countdown = ({ targetDate }) => {
  const [state, setState] = useState({
    currentTime: new Date(),
    isCountdownFinished: false,
  });

  useEffect(() => {
    const intervalId = setInterval(() => {
      const newCurrentTime = new Date();
      setState({
        currentTime: newCurrentTime,
        isCountdownFinished: newCurrentTime >= targetDate,
      });
    }, 1000);

    return () => clearInterval(intervalId);
  }, [targetDate]);

  if (state.isCountdownFinished) {
    return <p>倒计时结束!</p>;
  }

  const remainingTime = targetDate - state.currentTime;
  const days = Math.floor(remainingTime / (1000 * 60 * 60 * 24));
  const hours = Math.floor(
    (remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
  );
  const minutes = Math.floor((remainingTime % (1000 * 60 * 60)) / (1000 * 60));
  const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000);

  return (
    <p>
      距离{targetDate.toLocaleString()}还有:
      {days}天{hours}小时{minutes}分钟{seconds}秒
    </p>
  );
};

export default Countdown;

第三种方法:使用useRef

第三种方法使用useRef来存储倒计时时间,并在组件挂载时启动倒计时。这使得代码更加高效,因为我们只需要在组件挂载时设置一次倒计时,而不需要在每次更新时都检查倒计时是否结束。

import { useState, useEffect, useRef } from "react";

const Countdown = ({ targetDate }) => {
  const ref = useRef(null);
  const [isCountdownFinished, setIsCountdownFinished] = useState(false);

  useEffect(() => {
    const intervalId = setInterval(() => {
      const newCurrentTime = new Date();
      ref.current = targetDate - newCurrentTime;

      if (ref.current <= 0) {
        clearInterval(intervalId);
        setIsCountdownFinished(true);
      }
    }, 1000);

    return () => clearInterval(intervalId);
  }, [targetDate]);

  if (isCountdownFinished) {
    return <p>倒计时结束!</p>;
  }

  const remainingTime = ref.current;
  const days = Math.floor(remainingTime / (1000 * 60 * 60 * 24));
  const hours = Math.floor(
    (remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
  );
  const minutes = Math.floor((remainingTime % (1000 * 60 * 60)) / (1000 * 60));
  const seconds = Math.floor((remainingTime % (1000 * 60)) / 1000);

  return (
    <p>
      距离{targetDate.toLocaleString()}还有:
      {days}天{hours}小时{minutes}分钟{seconds}秒
    </p>
  );
};

export default Countdown;

总结

以上三种方法都是使用hooks实现倒计时的有效方法。第一种方法最简单,但代码相对冗长。第二种方法更加简洁,但需要使用两个useState。第三种方法最有效率,但需要使用useRef。您可以根据自己的需求选择合适的方法。