Project 51 of 100 - Everyone Needs to Build a Pomodoro
Tags: react, 100daysofcode, javascript, netlify
Published: 2021-02-25 07:10:12

*Hey! I'm on a mission to make 100 React.js projects ending March 31st. Please follow my dev.to profile or my [twitter](https://www.twitter.com/jwhubert91) for updates and feel free to reach out if you have questions. Thanks for your support!*

Link to the deployed project: [Link](https://100-react-projects-day-51-popovic-pomodoro.netlify.app/)
Link to the repo: [github](https://github.com/jwhubert91/100daysofreact/tree/master/day-51-popovic-pomodoro)

So, I'm not going to lie to you. I completely stole the Javascript for this project from a recent Dev.to post by programmer and rising Youtuber Aleks Popovic- here's his [recent article](https://dev.to/alekswritescode/infinite-pomodoro-app-in-react-52jj), and here's his [Youtube channel](https://www.youtube.com/watch?v=9z1qBcFwdXg&feature=emb_logo&ab_channel=AleksPopovic) which you **should follow** :)

The thing is, I've made [little Pomodoro apps](http://100days100projects.com/day9-pomodoroTimer/pomodoro.html) before (in pure html and JS), and like what happens so often in programming- sometimes you do something that gives you a headache and you just never want to do it again. For me, that was figuring out how to perform the Javascript countdown function and output a standard clock format for the minutes and seconds like we have here. I've wanted to build a full-featured Pomodoro application in React for a while so having another, more venerable programmer create the most important clockwork allows you to piggy-back and build other useful features on top of it. Also Aleks' Javascript is more elegant and concise than my original Pomodoro was so it's nice to practice with.

Today I give you the Popovic Pomodoro. It consists of a bit of styling, an `App` component and a `Pomodoro` component. I also gave mine a header. We'll go over the `Pomodoro` component in depth since that's where the real action is.

First, we import `useState` and `useEffect` into our functional component and create three pieces of state- `minutes`, `seconds`, and `displayImage`. 

```
import React,{useState,useEffect} from 'react'

function Pomodoro() {
  const [minutes,setMinutes] = useState(24);
  const [seconds,setSeconds] = useState(59);
  const [displayMessage,setDisplayMessage] = useState(false);

return () {...}
}
```

Next, inside our return statement we write the structure of our component's JSX. We have a div with the class "message" for our message and a div with the class "timer" for all of the timer action.

```
  return (
    <div className='pomodoro'>
      <div className='message'>
        {displayMessage && <div>Break time! New session starts in:</div>}
      </div>
      <div className='timer'>
       :
      </div>
    </div>
  )
```

As you can see, we only display the message text if `displayMessage` is true. This is done with conditional rendering.

For the timer, we knew we have to display a human-readable clock in the standard format, which is not the format that computers display numbers. For example, if there is 1 minute and 1 second left on the timer, it must be displayed as "1:01" rather than the computer's preferred "1:1". To do that we define variables for this before the return statement and then call them in the `timer` element.

```
const timerMinutes = minutes < 10 ? `0${minutes}` : minutes;
const timerSeconds = seconds < 10 ? `0${seconds}` : seconds;

return (
  ...
  <div className='timer'>
    {timerMinutes}:{timerSeconds}
  </div>
)
```

Ok, lastly, for the countdown functionality, we will have to use `useEffect` to re-render the component only under select conditions. We will also have to use the native Javascript setInterval() method to create the timer. It isn't perfectly accurate but it's usually within about a second of accuracy for a 25 minute timer, which is good enough for me.

```
  useEffect(() => {
    let interval = setInterval(() => {
      clearInterval(interval);

      if (seconds === 0) {
        if (minutes !== 0) {
          setSeconds(59);
          setMinutes(minutes - 1);
        } else {
          let minutes = displayMessage ? 24 : 4;
          let seconds = 59;

          setSeconds(seconds);
          setMinutes(minutes);
          setDisplayMessage(!displayMessage);
        }
      } else {
        setSeconds(seconds - 1);
      }
    }, 1000)
  },[seconds,minutes,displayMessage])
```

In plain English (or verbal pseudo-code) what this is doing is creating an interval that runs every 1000 milliseconds or 1 second. At the end of each second we clear the interval from running. This is really important because without clearing the interval the browser will keep making new ones as the old ones are still running and then your timer will start jumping around, and you'll have a memory leak.

Then, if seconds are zero, we either restart the seconds timer back at 59 to count down another minute, or if `minutes` is equal to zero, we set the `displayMessage` bool to true and start the break timer. This is all done with a series of clever ternaries that keep the Pomodoro operation short. If seconds are not zero, then we remove 1 from `seconds` and since that piece of state is displayed on screen, it keeps reducing the counter the user sees by 1 second.

I'll follow up on this project later in the week to build out some extra functionality, but for today, there's your Popovic Pomodoro!

As always, please [follow me on Twitter](https://www.twitter.com/jwhubert91) for additional updates and valuable shares from other developers. Also follow Aleks, since he's the creator of this little gem- his blog is [here](https://dev.to/alekswritescode).