• Home
  • React
  • React Hooks – useReducer hook example

React Hooks – useReducer hook example



UseReducer is an alternative to useState. It works better when you have complex state logic that involves multiple sub-values (e.g. if your state is multidimensional object) or when the next state depends on the previous one. UseReducer hook accepts a reducer of type (state, action) => newState, and returns the current state paired with a dispatch method:

const [state, dispatch] = useReducer(reducer, initialArg, init);

You can pass initial value of state as second argument:

const [state, dispatch] = useReducer(
    reducer,
    {count: initialCount}
  );


Lets see it on example. We have counter, which shows numbers starting from 0 (our initial state), and two buttons: +1 and -1. When we click +1 button, counter number changes its value and color to green, when we click -1 button, counter number changes its value and color to red. Initial color of counter is gray, and counter get this color, when we click third button, named reset, which also resets counter to 0.

Our component returns buttons:

return (
    <div className="App">
      <p> Counter: <span style={{color: counter.color }}> {counter.count} </span></p>
      <button onClick={() => setCounter({type: "add"})} > +1 </button>
      <button onClick={() => setCounter({type: "substract"})} > -1 </button>
      <div>
         <button onClick={() => setCounter({type: "reset", setInitState: initState})} > reset </button>
      </div>
    </div>
);


And our state is an object, with two values: count and color:

const initState = {count: 0, color: "gray"}

// state - Declaring new state variable, called "counter" and initial count state
const [counter, setCounter] = useReducer(switchOption, initState);


Now we want to write switchOption function, which changes our state depends on action (button that we clicked):

const switchOption = (state, action) => {
    switch (action.type) {
        case 'add':
           return {count: state.count + 1, color: "green"};
        case 'substract':
            return {count: state.count - 1, color: "red"};
        case "reset":
            return action.setInitState;
        default:
            return {count: state};
    }
}


Whole component code looks like this:

import React, { useReducer } from 'react';

const HookExample = () => {

    const switchOption = (state, action) => {
        switch (action.type) {
            case 'add':
                return {count: state.count + 1, color: "green"};
            case 'substract':
                return {count: state.count - 1, color: "red"};
            case "reset":
                return action.setInitState;
            default:
                return {count: state};
        }
    }

    const initState = {count: 0, color: "gray"}

    // state - Declaring new state variable, called "counter" and initial count state
    const [counter, setCounter] = useReducer(switchOption, initState);
 
  return (
    <div className="App">
      <p> Counter: <span style={{color: counter.color }}> {counter.count} </span></p>
      <button onClick={() => setCounter({type: "add"})} > +1 </button>
      <button onClick={() => setCounter({type: "substract"})} > -1 </button>
      <div>
         <button onClick={() => setCounter({type: "reset", setInitState: initState})} > reset </button>
      </div>
    </div>
  );
}

export default HookExample;

You can import HookExample component to App component to works fine.

Click on DEMO to see how useReducer hook works

You can find this code in repo: https://github.com/love-coding-pl/React-Hooks-Examples/tree/Hook-2-useReducer

Joanna

Leave a Reply

Your email address will not be published. Required fields are marked *