React 中的倒数计时器

新手上路,请多包涵

我在 JavaScript 中看到了很多倒数计时器,并希望在 React 中使用它。

我借用了我在网上找到的这个功能:

secondsToTime(secs){
    let hours = Math.floor(secs / (60 * 60));

    let divisor_for_minutes = secs % (60 * 60);
    let minutes = Math.floor(divisor_for_minutes / 60);

    let divisor_for_seconds = divisor_for_minutes % 60;
    let seconds = Math.ceil(divisor_for_seconds);

    let obj = {
        "h": hours,
        "m": minutes,
        "s": seconds
    };
    return obj;
  };

然后我自己写了这段代码

  initiateTimer = () => {
    let timeLeftVar = this.secondsToTime(60);
    this.setState({ timeLeft: timeLeftVar })
  };

  startTimer = () => {
    let interval = setInterval(this.timer, 1000);
    this.setState({ interval: interval });
  };

  timer = () => {
    if (this.state.timeLeft >0){
      this.setState({ timeLeft: this.state.timeLeft -1 });
    }
    else {
      clearInterval(this.state.interval);
      //this.postToSlack();
    }
  };

目前onclick会将屏幕上的时间设置为: Time Remaining: 1 m : 0 s

但它不会将其减少到 Time Remaining: 0 m : 59 s 然后 Time Remaining: 0 m : 58 s 等等

我想我需要使用不同的参数再次调用该函数。我该怎么做呢?

编辑:我忘了说,我想要这个功能,这样我就可以使用秒到分和秒

原文由 The worm 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 764
2 个回答

您必须在剩余的 setState 下每秒设置一次(每次调用间隔时)。这是一个例子:

 class Example extends React.Component {
 constructor() {
 super();
 this.state = { time: {}, seconds: 5 };
 this.timer = 0;
 this.startTimer = this.startTimer.bind(this);
 this.countDown = this.countDown.bind(this);
 }

 secondsToTime(secs){
 let hours = Math.floor(secs / (60 * 60));

 let divisor_for_minutes = secs % (60 * 60);
 let minutes = Math.floor(divisor_for_minutes / 60);

 let divisor_for_seconds = divisor_for_minutes % 60;
 let seconds = Math.ceil(divisor_for_seconds);

 let obj = {
 "h": hours,
 "m": minutes,
 "s": seconds
 };
 return obj;
 }

 componentDidMount() {
 let timeLeftVar = this.secondsToTime(this.state.seconds);
 this.setState({ time: timeLeftVar });
 }

 startTimer() {
 if (this.timer == 0 && this.state.seconds > 0) {
 this.timer = setInterval(this.countDown, 1000);
 }
 }

 countDown() {
 // Remove one second, set state so a re-render happens.
 let seconds = this.state.seconds - 1;
 this.setState({
 time: this.secondsToTime(seconds),
 seconds: seconds,
 });

 // Check if we're at zero.
 if (seconds == 0) {
 clearInterval(this.timer);
 }
 }

 render() {
 return(
 <div>
 <button onClick={this.startTimer}>Start</button>
 m: {this.state.time.m} s: {this.state.time.s}
 </div>
 );
 }
 }

 ReactDOM.render(<Example/>, document.getElementById('View'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
 <div id="View"></div>

原文由 Fabian Schultz 发布,翻译遵循 CC BY-SA 4.0 许可协议

这是一个使用钩子的解决方案, 计时器 组件,我正在用钩子复制上面相同的逻辑

import React from 'react'
import { useState, useEffect } from 'react';

const Timer = (props:any) => {
    const {initialMinute = 0,initialSeconds = 0} = props;
    const [ minutes, setMinutes ] = useState(initialMinute);
    const [seconds, setSeconds ] =  useState(initialSeconds);
    useEffect(()=>{
    let myInterval = setInterval(() => {
            if (seconds > 0) {
                setSeconds(seconds - 1);
            }
            if (seconds === 0) {
                if (minutes === 0) {
                    clearInterval(myInterval)
                } else {
                    setMinutes(minutes - 1);
                    setSeconds(59);
                }
            }
        }, 1000)
        return ()=> {
            clearInterval(myInterval);
          };
    });

    return (
        <div>
        { minutes === 0 && seconds === 0
            ? null
            : <h1> {minutes}:{seconds < 10 ?  `0${seconds}` : seconds}</h1>
        }
        </div>
    )
}

export default Timer;

原文由 Masood 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题