DEV Community

loading...
Cover image for Project 72 of 100 - React Redux Pomodoro

Project 72 of 100 - React Redux Pomodoro

jwhubert91 profile image James Hubert ・2 min read

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.

Discussion (0)

Forem Open with the Forem app