Project: A Pomodoro Timer In React
Tags: portfolio, javascript, react, webdev
Published: 2021-05-28 13:38:10

# Intro
I recently created a Pomodoro timer in React, as part of the Free Code Camp front end course. The task involved creating a Pomodoro timer, which counts down from a predefined number of session minutes, then switches to a break timer, which counts down a specified break length. The session and break lengths can be altered, and the timer can be stopped and reset:

![pomodor-screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lb79s82uice6oofsofzg.png)

# What I learned

I picked up some new things while working on this project.


## padStart
I found this string method useful when I was counting down to single seconds, but wanted them to display with a leading zero.

It takes a number and a string as parameters, then adds copies of that string to the start until the entire string length is equal to the first parameter.

Therefore my usage was `second.padStirng(2, '0')`, which adds zeroes to the seconds output to ensure it is always a 2 digit number.

See more [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart)

## setState callbacks
I had a situation where I wanted to start the timer after setting `isRunning` to true. I initially started the timer after setting the state. This did not work because the `setState` changes are asynchronous, so the tick method was acting as though `isRunning` was false.

To combat this, the `setState` method has a callback parameter. Here we can add behaviour that will happen immediately after `isRunning` is set to true. Calling the tick method from the callback made the timer start ticking as expected.

See more [here](https://reactgo.com/react-setstate-callback/)

## setTimeout
I wanted a way to get the timer to update every second. I was able to do this using the `setTimeout` Javascript method. This method takes a method as a parameter and a time in milliseconds. It then calls the method after the specified time. I could put this in a loop to do it the number of times defined in the session length. 

There is also a `setInterval` method which works similarly, but happens an infinite number of times or until `clearInterval` is called.

See more [here](https://www.w3schools.com/jsref/met_win_settimeout.asp)

## Audio element (HMTL5)
I needed to play a beep sound when the time runs out.  A new HTML element was added in HTML5 that does what I need. The `<audio>` tag allows the user to specify a source, then there are DOM methods, that allow playing, stopping and restarting the source audio .

See more [here] (https://www.w3schools.com/html/html5_audio.asp#:~:text=HTML5%20Audio.%20Audio%20on%20the%20Web.%20Before%20HTML5%2C,browser%20version%20that%20fully%20supports%20the%20%3Caudio%3E%20element)

## React refs
I couldn't directly access the audio element in my React component to use its methods. To get around this we can use refs. We create a ref variable in the component:

`this.beepRef = React.createRef();`

and attach this to the audio element:

`<audio ... ref={this.beepRef} .../>`

 Now we can call the audio methods on this reference within the component's lifecycle:

`this.beepRef.current.play();`

See more [here](https://reactjs.org/docs/refs-and-the-dom.html)

## Importing a script into a React component
I wanted to test my solution using a script file that FreeCodeCamp had provided. I did not know how to directly add a script file in. I initially tried adding a script tag to the render method, but this did not run the script. I then discovered that I needed to add it into the document during the componentWIllMount stage of the life cycle:

```
componentWillMount() {
    const scriptTag = document.createElement("script");
    scriptTag.src =
      "https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js";
    scriptTag.async = true;
    document.body.appendChild(scriptTag);
  }
```

See more [here] (https://reactgo.com/render-script-tag-component/)

# Conclusion
This was a great project to get some more practice with creating custom components and I also learnt quite a bit about how to implement timers.

You can see the app running [here](https://natravenhill.com/PomodoroTimer/)