Timer component using setInterval() + clearInterval()

Journaling a recent bug fix and code refactor

TLDR: Set a variable for setInterval() so you can clearInterval() later.


Recently, as part of a coding assignment I built a timer using React. The specific instructions aside, it was clear what the main functionality of the Timer component should be. It would need a way to increment the time values and update the component continually.

For those unfamiliar, in Javascript, this can be achieved using a method called setInterval(). It will take a callback and repeatedly call it at a fixed time delay between each call.

In the first iteration of the assignment, I decided my code would benefit from the use of a helper function to create setInterval() methods for each time unit seen above. Minutes, seconds and centiseconds (hundredths of a second). Each of these units were being kept track of individually in the class’ state and updated at various intervals indicated below.

I was happy with how readable the code was and the code reuse. However, after some observation of the timer in effect, I noticed an undesirable effect. A task of the assignment wanted a split to highlight the clicked split, reset the timer to the split’s time, and remove all splits below. You can see the effect in the above gif.

When the split was removed, the timer would reset correctly but the intervals had not changed so sometimes you could see the time go up a second at something like 50 centiseconds or 36 centiseconds, etc.

I identified the issue could be solved by resetting the setInterval() functions. Also although it initially made sense to increment each time unit independently, it was the main cause of the seconds unit incrementing when it clearly shouldn’t. Also in order to stop/reset the setInterval() I would need the clearInterval() method as well. But to use clearInterval() I have to store the setInterval() method as a variable accessible later.

The helper function was removed and the minutes and seconds time units will update dependent on a mix of the other time units. I also saved the setInterval() method to a local variable intervals which can later be accessed within the Timer component class through this.intervals.

The initial version used many if/else statements to confirm the conditionals, but through the use of ES6 destructuring, nested ternary operators and arrow functions, the conditions of updating a time unit were better detailed individually.

Finally I added the clearInterval() method followed immediately by calling the starter function that contained the setInterval(). Because setInterval() functions go into effect immediately, it is good practice to save it to a variable. In my earlier code it would be impossible to clearInterval() on these lines.

let hunds = this.timeIntervalSetter("hundredths", 100, 10)
// also no effect because hunds is not where setInterval() is called but timeIntervalSetter() is.
this.timeIntervalSetter("hundredths", 100, 10)
// no effect because timeIntervalSetter is not the specific reference

Thanks for reading! I am open to receiving any feedback regarding my code and thought process.