by Tiffany White
My latest bugfix: or, how I went spelunking in someone else’s code
I love CodeSandbox. It has pretty much replaced CodePen for me unless I am fiddling around with CSS or freeCodeCamp front-end projects.
I like going through the sandboxes and picking out different ones to look at, take apart, and figure out how they work.
While going through React Tutorial for Beginners by Kent C. Dodds on Egghead.io, I decided I would look for sandboxes that correlated with the course, as I was using Codesandbox to build out the stopwatch we were building in that course.
I found a sandbox which I forked and found to be buggy.
Why didn’t the stopwatch work? Glancing at the code for a few seconds, I saw some obvious problems right away.
Here is an example of the stopwatch being broken:
The first thing I noticed was on line 7:
Date.now() needs parentheses.
Date is an an object constructor with
.now() being a method. When we click on the start button, React doesn’t know what to do here; we aren’t setting the state of
lapse to be a number, which we expect. By adding the parentheses, we get the start button to work. No more
But now we have another problem: the timer won’t stop.
I also removed the
console.log(Math.random()); because I felt it was unnecessary.
Bugfix 2: Getting the Stopwatch to Stop and Clear
Each time the button is clicked, we set the state to either
lapse. The timer runs when we click
start but clicking
clear doesn’t seem to work. How can we fix this?
We can create a timer update function that accepts the current state. We can accomplish this by using native DOM APIs such as
clearInterval(). We can run conditional logic to see if the timer is running:
Date.now() to get the timestamp in ms, and assign it a
startTime variable to compare the current time to the amount of time that has passed. When we click the start button, it sets the
startTime to the current timestamp. We also need to return a new state as state is not mutable.
Okay so this partially works. But as you can see below, if I click
clear while the stopwatch timer is running, it doesn’t clear the timer, and it also doesn’t allow me to stop the timer, either.
How do we fix this particular bug?
If we look back at the previous code, we can see we are using
clearInterval() to reset the stopwatch timer. In our current iteration, our
handleOnClear method is just setting the state without clearing the previous state.
We can fix this by adding
clearInterval() and passing in the timer function to the
handleOnClear method to clear the state.
This will give us the results we want.
There is a memory leak in this particular iteration. The timer will run until it is explicitly stopped in the DOM. We can use a React lifecycle method to stop all processes in the DOM when this component is mounted or unmounted.
For this we can use
componentWillUnmount to tell React to unmount the component once it is done rendering.
Thoughts and Conclusions
I find it much more enjoyable fixing other people’s bugs than my own. This was a fun exercise and I plan on doing it more regularly and blogging about it.
This stopwatch is a stupid simple component but if you are just scratching the surface of React like I am, I am sure digging into something like this stopwatch and figuring out how it works is an excellent exercise and use of one’s time.