1

I've been doing a bit of research on implementations of timers in react redux. There seems to be 2 primary schools of thought.

Using actions only for stop/start/reset

Explained in this SO post(Creating a stopwatch with redux).

Using an action for each tick of the stopwatch as well

I've read about this in this react/redux issue. Seems even Dan Abramov commented on this one. So maybe vouches for this methodology?


Is there a best practice for this? or does it depend on the situation? I'm making a timer for my application to track length of time for a certain task and I just want to implement it the right way, the first time. My initial thoughts are leaning towards option 1.

Community
  • 1
  • 1
Andrew Kim
  • 3,145
  • 4
  • 22
  • 42

1 Answers1

3

There are quite a few situations where the "tick" idea just doesn't work:

  • If the timer needs to keep running when the page is closed, or
  • If the user is on a slow device or their computer freezes up, the timer can "drift" as tick events are delayed or skipped.

A better solution for your Redux state would probably be:

tasks: [
    { id: '6d5d9f59-a65c-44ad-bf76-b69ef89b4f58',
      title: 'Task One',
      startTime: 1482160636032 },
    { id: '25a502e9-f2ef-4f65-bba6-723cc755c708',
      title: 'Task One',
      startTime: 1482160697663 }
]

Using this, you would only need to subtract Date.now () - task.startTime to get the elapsed time.

Then, for the timer, I would recalculate every second in the React component:

class Task extends Component {
    componentDidMount () { tick () }
    componentWillUnmount () { clearTimeout (timer) }
    tick () {
        // time until next second
        // won't drift with time
        const nextSecond = 1000 - Date.now () % 1000
        this.timer = setTimeout (tick, nextSecond)

        this.setState ({ elapsedTime: Date.now () - this.props.task.startTime })
    }
    render () { ...  }
}
Robbie Wxyz
  • 7,671
  • 2
  • 32
  • 47