Note:
useReducer is a hook that is used for state management
It's an alternative to useState
useState is built using useReducer
With useReducer function, we have two parameters
useReducer(reducer, initialState)
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
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.
When the action is increment, the new state becomes current state plus one.
When it's decrement, the new state will be current state minus one.
Action can be reset in which case the new state will be the initial state of zero.
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: