Search code examples
javascriptreactjstimermomentjs

Moment js for displaying a timer in mm:ss format


I have a timer that must be displayed in MM: SS format. My countdown times are: 30 min, 60 min, and 90 min. With the implementation below the 30 minutes and 60 minutes are displayed properly but the 90 minutes are shown initially as 30 minutes and when 30 minutes are passed it displays 60 minutes. The time from the state is readen in seconds and as a result, the options are 1800, 3600 and 5400 secs. Here is the implementation:

const calculateSessionTimeAt = limit => Date.now() + (limit * 1000); where limit is the seconds
this.state = { timer: this.props.calculateSessionTimeAt - Date.now() };

<span className="number">
          { formatTimerValue(timerValue, 'mm:ss') }
</span>

where formatTimerValue

const formatTimerValue = (timer, format) => moment().startOf('hour').add(timer, 'milliseconds').format(format);

Can you help me with what I'm missing?


Solution

  • Not sure why you need momentjs, if you have a timer you can set a value to the current date plus timer and check the difference between current date and that value every second.

    Here is an example of how you could do that:

    const { useState, useEffect } = React;
    //format single digit to double so 0 becomes '00'
    const pad = n => ('0' + n).slice(-2);
    //format amount of milliseconds to mm:ss
    const millisecondsToTimer = ms => {
      if (ms < 0) {
        return '0:00';
      }
      const minutes = Math.floor(ms / 60000);
      const seconds = pad(
        Math.floor((ms - minutes * 60000) / 1000)
      );
      return `${minutes}:${seconds}`;
    };
    function App() {
      const [end, setEnd] = useState();
      const [minutes, setMinutes] = useState(6);
      const [timer, setTimer] = useState();
      const start = () =>
        setEnd(Date.now() + minutes * 60000 + 100);
      useEffect(() => {
        if (!end) {
          return;
        }
        const t = setInterval(
          () => setTimer(millisecondsToTimer(end - Date.now())),
          1000
        );
        setTimer(millisecondsToTimer(end - Date.now()));
        return () => clearInterval(t);
      }, [end]);
      return (
        <div>
          <label>
            Minutes:
            <input
              type="number"
              value={minutes || ''}
              onChange={e => setMinutes(e.target.value)}
            />{' '}
          </label>
          <button onClick={start}>Start</button>
          <div>{timer}</div>
        </div>
      );
    }
    
    ReactDOM.render(<App />, document.getElementById('root'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
    <div id="root"></div>