Daniel Doubrovkine bio photo

Daniel Doubrovkine

aka dB., CTO at artsy.net, fun at playplay.io, NYC

Email Twitter LinkedIn Github Strava

In the previous post I added and removed list items. In this post I will implement a ticking timer.

The React Native ecosystem promises a rich set of components that work seamlessly together, much like the Ruby world. My first timer implementation used react-timer-machine, a fully controllable and customizable timer component.

$ yarn add react-timer-machine
import TimerMachine from 'react-timer-machine'

Time duration math is implemented by combining moment.js and moment-duration-format.

import moment from "moment";
import momentDurationFormatSetup from "moment-duration-format";
momentDurationFormatSetup(moment);

The timer itself will start as soon as the isMeetingStarted state is toggled.

<TimerMachine
  timeStart={1000}
  started={this.state.isMeetingStarted}
  countdown={false}
  interval={1000}
  formatTimer={(time, ms) =>
    moment.duration(ms, "milliseconds").format("h [hours], m [minutes], s [seconds]")
  }
/>

It works, except when it doesn’t. Expo doesn’t support background tasks and so the timer pauses when the app is backgrounded. A simple workaround is to keep track of start and end time, but we might as well get rid of the timer altogether.

We can rely on setInterval to call a method every second in the foreground and update the elapsed time by subtracting two timestamps. I find simulating a timer in this manner pretty neat, as it takes full advantage of React re-rendering components when state changes. It obviously wouldn’t be suitable for performing an action based on elapsed time since no events fire in the background.

this.setState({ elapsedTime: moment().diff(this.state.meetingStartedAt) })

You can see this code in 33-minutes-app@0f1df4. In the next post I will wire up this React Native client app to a Rails GraphQL API.