react+hooks 定时器

455 阅读1分钟

第一种

import {useState, useEffect} from "react";

export default function App() {
  const [count, setCount] = useState(20);

  useEffect(() => {
    let timerId: any = null;
    const run = () => {
      if (count <= 0) {
        return () => {
          timerId && clearTimeout(timerId);
        };
      }
      setCount(count - 1);
      timerId = setTimeout(run, 1000);
      return;
    };
    timerId = setTimeout(run, 1000);
    return () => {
      timerId && clearTimeout(timerId);
    };
  }, [count]);

  return (
    <div className="App">
      <h2>{count}</h2>
      <button onClick={() => {
        setCount(0)
      }}>停止
      </button>
      <button onClick={() => {
        setCount(20)
      }}>开始
      </button>
    </div>
  );
}

第二种

import {useState} from 'react'
import {useTimer} from './UseTimer'
import {PageContainer} from '@ant-design/pro-layout'
import {Button} from 'antd';

export default function Index() {
  const [IsShow, setIsShow] = useState(true)
  const {num, start} = useTimer(600, () => {
    setIsShow(true)
  })


  const isShow = () => {
    setIsShow(false)
    start()
  }

  return (
    <PageContainer>
      <div className={''}>
        <Button disabled={!IsShow} onClick={isShow}>
          {IsShow ? '显示' : '还有' + num + '秒恢复'}
        </Button>
      </div>

    </PageContainer>

  )
}

import {useTimer} from './UseTimer'

import {useState, useEffect, useRef} from 'react'
// 第一参数为你定时的数字
// 第二参数为你定时结束时想做的事
// 返回的第一参数为随时间变化而变化的值
// 返回第二参数为触发函数
export function useTimer(Num: any, callBack = () => {
}) {
  const [num, setNum] = useState(Num)
  const ref: any = useRef(null)
  // 调用这个方法,开始倒数
  const start = () => {
    setNum(Num) // 重新赋值
    // 定时器
    ref.current = setInterval(() => {
      setNum((item: any) => item - 1)
    }, 1000)
  }
  // 倒数为0 关闭定时器
  useEffect(() => {
      if (num === 0) {
        return () => {
          clearInterval(ref.current) // 关闭定时器
          callBack() // 自己想做的事
        }
      }
      return
    },
    [num]
  )

  // 解决当正在计数的组件开始倒数 删除组件导致无法取消定时器
  useEffect(() => {
    return () => {
      clearInterval(ref.current)
    }
  }, [])
  // 返回可变值 与 触发函数
  return {
    num, // 可变值
    start // 触发函数
  }
}


第三种:

import {useState, useEffect} from "react";
const Index = () => {
  const [time, setTime] = useState();
  //倒计时
  const countDown = (munite: any, second: any) => {
    let m = munite;
    let s = second;
    let m2;
    let s2;
    const tiem = setInterval(() => {
      s -= 1;
      if (s < 0) {
        s = 60;
        m--;
        if (m < 0) {
          localStorage.removeItem('endingTime');
          // @ts-ignore
          setTime('00分00秒')
          clearTimeout(tiem);
          return;
        }
      }
      m2 = m < 10 ? '0' + m : m;
      s2 = s < 10 ? ('0' + s) : s;
      // @ts-ignore
      setTime(m2 + '分' + s2 + '秒');
    }, 1000)
  }

  const endTime = () => {
    const endingTime = new Date().getTime() + 1 * 60 * 1000;//可改变
    const num = Number(localStorage.getItem("endingTime"))
    if (localStorage.getItem("endingTime")) {
      // @ts-ignore
      const diff = num - new Date().getTime();
      if (diff <= 0) {
        localStorage.removeItem('endingTime');
      } else {
        const m = Math.floor(diff / 1000 / 60);
        const s = Math.floor(diff / 1000 - m * 60);
        countDown(m, s);
        const s2 = s < 10 ? ('0' + s) : s;
        // @ts-ignore
        setTime(m + '分' + s2 + '秒');
      }
    } else {
      countDown(0, 120);//可改变
      // @ts-ignore
      setTime(60 + '秒');//可改变
    localStorage.setItem("endingTime", String(endingTime));
    }
  };
  useEffect(() => {
    endTime();
  }, [])
  return (
    <div>
      <button onClick={() => {
        endTime();
      }}>{time}
      </button>
    </div>
  );

}

export default Index;