Building A ReactJS Timer Component with Hooks (useState)

Here’s an easy way to build a timer using ReactJS.

For this simple app, we will use useEffect and useState hooks to initialize and store our app state.

What this timer does?

It’s a simple timer which goes from 0 to ∞.

You click the button to initiate your counter and it goes on forever. To make it a little interesting, we also have a button which will set the timer to the value of 0 on clicking.

First, if you just wish to see the code, here’s it.

react-timer-folder-structure
Timer app folder structure
// App.js
import React, { useState } from "react";
import "./styles.css";

export default function App() {
  const [count, setCount] = useState(0);
  const [isCounting, setIsCounting] = useState(false);

  const startCount = () => {
    setInterval(() => {
      setCount(count => count + 1);
    }, 1000);

    setIsCounting(true);
  };

  const resetCount = () => setCount(0);

  const Timer = (count) => (
    <>
      <p>Count: {count}</p>
      <div className="buttons">
        <button onClick={resetCount}>Reset</button>
        <button onClick={startCount} disabled={isCounting}>
          Start
        </button>
      </div>
    </>
  );

  return (
    <div className="App">
      <Timer count={count}/>
    </div>
  );
}
// index.js
import React from "react";
import ReactDOM from "react-dom";

import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);
/* styles.css */
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

.App {
  font-family: sans-serif;
  background-color: #39cccc;
  color: #001f3f;
  min-height: 340px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 2.5em;
  flex-direction: column;
}

.buttons {
  margin-top: 0.5em;
}

button {
  text-transform: uppercase;
  margin: 1em;
  padding: 1em 2em;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  color: #37474f;
  border-color: #37474f;
}

button:focus {
  border: none;
}

button:hover {
  color: white;
  background-color: #001f3f;
}

button:disabled {
  cursor: not-allowed;
  background-color: #37474f;
  color: white;
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta name="theme-color" content="#000000" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <title>React Timer App</title>
  </head>

  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
  </body>
</html>
// package.json
{
  "name": "react_timer_app",
  "version": "0.0.1",
  "description": "React Timer App",
  "main": "src/index.js",
  "dependencies": {
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-scripts": "3.4.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

Initializing the counter

In our app, the counter doesn’t start automatically. For that, we have the start button.

  const [count, setCount] = useState(0);
  const [isCounting, setIsCounting] = useState(false);

On the top of the App function, we have initialized two states for count and isCounting.

Updating the counter

The start button has an onClick handler where we initialize a setInterval function. This starts the counter and updates the count‘s value every 1000ms.

setCount(count => count + 1);

Similar to the Start button, we have the Reset button. This changes the count‘s value to 0 on clicking using the following function.

  const resetCount = () => setCount(0);

As you can see, the app structure is pretty simple. You only have a count state which we are manipulating using React.useState function.

,

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.