DEV Community

Cover image for Building a React Counter App with useState and useReducer.
Fisayo
Fisayo

Posted on

Building a React Counter App with useState and useReducer.

In this post, I will go through how to build a counter app in react using a useState and useReducer custom hooks.

useState and useReducer?

Usually, when we want to handle simple states in React, we heavily rely on the useState hook. The useState hook helps in managing linear states. However, sometimes we get to deal with more complex state logic, where the multiple sub-values or next state depends on the previous state or might be deep updates are required to handle the state in React.
Luckily react has come up with something to solve the problem of managing complex state in a concise and elegant manner which is the useReducer hook.

These are the list of dependencies used for this app

  • react

  • react-dom

  • react-router-dom

  • react-error-boundary

STEPS

Build react app

npx create-react-app myapp
Enter fullscreen mode Exit fullscreen mode

NB: 'myapp' can be any name of your choosing.

Enter into the project's root.

cd myapp
Enter fullscreen mode Exit fullscreen mode

Start the app

npm start
Enter fullscreen mode Exit fullscreen mode

Counter 1 (useReducer Hook)

Import the useReducer hook from react.

import { useReducer } from "react";
Enter fullscreen mode Exit fullscreen mode

CODE SET UP

import { useReducer } from "react";

const UseReducer = () => {
  function setValue(value, count) {
    let num = Number(value);
    if (String(num) == "NaN" || value == "") {
      return count;
    }
    return num;
  }

  const reducer = (count, action) => {
    switch (action.type) {
      case "setValue":
        return setValue(action.payload, count);
      case "increment":
        return ++count;
      case "decrement":
        return --count;
      case "reset":
        return 0;
      default:
        return count;
    }
  };

  const [count, dispatch] = useReducer(reducer, 0);

  return { count, dispatch };
};

const Reducer = () => {
  const { count, dispatch } = UseReducer();

  const Increment = () => {
    dispatch({ type: "increment" });
  };
  const Decrement = () => {
    dispatch({ type: "decrement" });
  };
  const Reset = () => {
    dispatch({ type: "reset" });
  };

  return (
    <main className="app">
      <h1 className="h1-design">
        Welcome to the useReducer page... <br /> Check out the Counter!
      </h1>
      <div className="counter">
        <input
          type="text"
          placeholder="set counter value"
          onChange={(e) =>
            dispatch({ type: "setValue", payload: e.target.value })
          }
        />

        <h2>COUNTER = {count}</h2>
        <div className="btn">
          <button className="increment" onClick={Increment}>
            Increment
          </button>
          <button className="decrement" onClick={Decrement}>
            Decrement
          </button>
          <button className="reset" onClick={Reset}>
            Reset
          </button>
        </div>
      </div>
    </main>
  );
};
export default Reducer;

Enter fullscreen mode Exit fullscreen mode

Counter 2 (useState Hook)

Again, we import the useState hook from react.

import {useState} from "react";
Enter fullscreen mode Exit fullscreen mode

CODE SET UP

import {useState} from 'react'
function UseCounter() {
    const [value, setValue] = useState(0);
    const increment = () => {
      setValue((prevValue) => prevValue + 1);
    };

    const decrement = () => {
      setValue((prevValue) => prevValue - 1);
    };

    const reset = () => {
      setValue(0);
    };

    function setInput(value) {
        let num = Number(value)
        if(String(num) == "NaN" || value == "") {
            return value;
        }
        return num;
      }
    return [value, increment, decrement, reset, setInput]
}
const Counter = () => {
  return (
    <main className="app">
      <h1 className="h1-design">
        Welcome to the custom Hook page... <br /> Check out the Counter!
      </h1>
      <div className="counter">
        <input
          type="text"
          placeholder="set counter value"
          onChange={setInput}
        />
        <h2>COUNTER = {value}</h2>
        <div className="btn">
          <button className="increment" onClick={increment}>
            Increment
          </button>
          <button className="decrement" onClick={decrement}>
            Decrement
          </button>
          <button className="reset" onClick={reset}>
            Reset
          </button>
        </div>
      </div>
    </main>
  );
};

export default Counter;
Enter fullscreen mode Exit fullscreen mode

There you have it!
Your react counter app using the useState and useReduce hooks.
I hope this article was helpful.

Feel free to check out the source code in my GitHub repository.
Here is also the link to the live app

Thank you for reading.

Top comments (0)