Understanding useReducer hook

Understanding useReducer hook

Note:

  1. useReducer is a hook that is used for state management

  2. It's an alternative to useState

  3. useState is built using useReducer

  4. With useReducer function, we have two parameters

    useReducer(reducer, initialState)

  5. The reducer function accepts two parameters that is the current state and an action and returns a new state.

    newState = reducer(currentState, action)

    The action parameter dictates the state transition from the current state to the new state

  6. useReducer returns a pair of values, [newState, dispatch].

    The dispatch method is used to specify the action

Steps to work with useReducer.

Step 1: Import useReducer from React

import React, { useReducer } from 'react'

Step 2: Calling the useReducer function in our functional component

const [count, dispatch] = useReducer(reducer, initialState)

Similar to useState, useReducer returns a pair of value(that is the count and dispatch) which we can get hold of using the array destructuring syntax. it returns the currentState which we called as count paired with the dispatch method. The dispatch method allows us to execute the code that corresponds to a particular action.

Step 3: Defining the initial state and the reducer function

const initialState = 0
const reducer = (state, action) => {
    switch (action) {
        case 'increment':
            return state + 1
        case 'decrement':
            return state - 1
        case 'reset':
            return initialState
        default:
            return state
    }
}

Recall that a reducer function accepts two values and returns one value. The two values accepted are the current state and the action.

An action is like an instruction to the reducer function. Based on what the action specified, the reducer function performs the necessary state transition. From the example above, we have three actions; increment, decrement, reset. The convention used to execute code based on the action is to use switch statement, so within the reducer function body, we added switch statement.

The switch expression is the action.

  1. When the action is increment, the new state becomes current state plus one.

  2. When it's decrement, the new state will be current state minus one.

  3. Action can be reset in which case the new state will be the initial state of zero.

  4. We can also have a default case for which the current state is returned without any changes.

Step 4: To get hold of the value to display in the jsx and also a way to call the reducer function with the appropriate action.

return (
        <div>
            <h2>{count}</h2>
            <button onClick={() => dispatch('increment')}>Increment</button>
            <button onClick={() => dispatch('decrement')}>Decrement</button>
            <button onClick={() => dispatch('reset')}>Reset</button>
        </div>
    )

To each of the buttons, a click handler is added. onClick is equal to an arrow function where we dispatch an action. For the increment button, we dispatched the increment action, for decrement button, we dispatched the decrement action and for reset, we dispatched the reset action.

To test it out, you include the file name in app.js

import React from 'react'
import CounterOne from './components/CounterOne'

function App() {
  return (
    <div>
      <CounterOne />
    </div>
  )
}

export default App

The full view of the counterOne file

import React, { useReducer } from 'react'

const initialState = 0
const reducer = (state, action) => {
    switch (action) {
        case 'increment':
            return state + 1
        case 'decrement':
            return state - 1
        case 'reset':
            return initialState
        default:
            return state
    }
}

function CounterOne() {
    const [count, dispatch] = useReducer(reducer, initialState)
    return (
        <div>
            <h2>{count}</h2>
            <button onClick={() => dispatch('increment')}>Increment</button>
            <button onClick={() => dispatch('decrement')}>Decrement</button>
            <button onClick={() => dispatch('reset')}>Reset</button>
        </div>
    )
}

export default CounterOne

The various outputs:

On increment:

On decrement:

On reset: