Project 72 of 100 - React Redux Pomodoro

jameshubert_com

James Hubert

Posted on May 9, 2021

Project 72 of 100 - React Redux Pomodoro

Hey! I'm on a mission to make 100 React.js projects ending May 31st. Please follow my dev.to profile or my twitter for updates and feel free to reach out if you have questions. Thanks for your support!

Link to today's deployed app: Link
Link to the repo: github

So I'm a big fan of the Pomodoro method. I think there are some times when it works well and others when it doesn't, but overall it's a great way to parcel out your time and to make sure you have those necessary breaks throughout your time at work.

Today I wanted to use React Redux to store the counter state in a Redux store using the react-redux npm package.

Redux is built using the Context API under the hood so the first step is wrapping your application in the React Redux {Provider} component at the root level.

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux'
import store from './redux'
import './index.css';
import App from './App';

ReactDOM.render(
    <Provider store={store}>
      <App />
    </Provider>,
  document.getElementById('root')
);
Enter fullscreen mode Exit fullscreen mode

The next step is to write your actions and reducer, and to create a store for Redux in a separate Javascript file.

import {createStore} from 'redux'

export function decrement() {
  return {
    type: "DECREMENT"
  }
}

export function resetCount() {
  return {
    type: "RESET"
  }
}

export function reducer(count, action) {
  switch (action.type) {
    case ("DECREMENT"):
      return count - 1
    case ("RESET"):
      return 1500
    default:
      return 1500
  }
}

const store = createStore(reducer);

export default store;
Enter fullscreen mode Exit fullscreen mode

The next step is to actually write out your React components, and import the connect() method from react-redux into the React component that will be using it.

import React,{useState,useEffect} from 'react'
import {connect} from 'react-redux'
import {decrement,resetCount} from '../redux'
import tomatoImage from '../images/tomato.png'

function Pomodoro(props) {
  const [isCounting,setIsCounting] = useState(false)
  const [hasCounted,setHasCounted] = useState(false)
  const [minutes,setMinutes] = useState(0)
  const [seconds,setSeconds] = useState(0)
  const [buttonClass,setButtonClass] = useState("play")

  useEffect(() => {
    setTimeState()
    if (props.count > 0 && isCounting) {
      // is counting and there's time left
      setTimeout(() => {
        props.decrement()
      },1000)
    } else if (props.count > 0 && isCounting) {
      // time has run out
      setIsCounting(false)
      setHasCounted(true)
      setButtonClass("play")
      props.resetCount()
    }
  },[props.count,isCounting])

  function setTimeState() {
    const minsRaw = Math.floor(props.count / 60);
    const secsRaw = props.count - (minsRaw * 60)

    const minsString = minsRaw.toString()
    const secsString = secsRaw.toString()

    const minsFinal = minsString.length < 2 ? "0"+minsString : minsString
    const secsFinal = secsString.length < 2 ? "0"+secsString : secsString

    setMinutes(minsFinal)
    setSeconds(secsFinal)
  }

  function handleClick() {
    // play & has not counted before
    if (!isCounting) {
      setIsCounting(true)
      setButtonClass("pause")
    }
    // pause
    else {
      setIsCounting(false)
      setButtonClass("play")
    }
  }

  return (
    ...
    // excluding JSX here because you probably know what 
    // Pomodoro html elements look like
  )
}

function mapStateToProps(state) {
  return {
    count: state
  }
}

const mapDispatchToProps = {
  decrement: decrement,
  resetCount: resetCount
}

export default connect(mapStateToProps, mapDispatchToProps)(Pomodoro)
Enter fullscreen mode Exit fullscreen mode

If you like projects like this and want to stay up to date with more, check out my Twitter @jwhubert91, I follow back! See you tomorrow for another project.

💖 💪 🙅 🚩
jameshubert_com
James Hubert

Posted on May 9, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related