The React useReducer hook is a very interesting hook that is basically an alternative to useState.
The hook looks something like this:
const [state, dispatch] = useReducer(reducer, initialState)
Let's explore it a bit further in order to understand it.
So, what is a reducer? A reducer is typically a switch statement that will change what happens to the state depending on what parameter (called action) is passed into the dispatch function, which is like a setState function.
A simple reducer will look something like this:
const reducer = (state,action) => {
switch (action.type){
case "increase":
return {...state, count: state.count + 1};
case "decrease":
return {...state, count: state.count - 1};
default:
break;
}
}
Then, for instance, to decrease the count by 1 using the action type "decrease", we would use our dispatch like this:
dispatch({type: "decrease"});
We can then get the count simply by using:
{state.count}
The full code might look something like this:
import React, { useReducer } from 'react'
const reducer = (state,action) => {
switch (action.type){
case "increase":
return {...state, count: state.count + 1};
case "decrease":
return {...state, count: state.count - 1};
default:
break;
}
}
const initialState = {
stuff: "stuff",
count: 0
}
const myComponent = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<button onClick={()=>dispatch({type: "decrease"})}>Decrease</button>
<span>Count: {state.count}</span>
<button onClick={()=>dispatch({type: "increase"})}>Increase</button>
</div>
)
}
export default myComponent;
Another trick for handling forms, especially ones with lots of fields, is the following:
const reducer = (state,action) => {
switch (action.type){
case "field":
return {
...state,
[action.field]: action.value
};
default:
break;
}
}
We can then edit, for example, our email field using the following dispatch:
onChange={e=>dispatch({type: "field", field: "email", value: e.target.value })}
This can be used to replace a lot of useState hooks for each field in a form.
You can also change multiple parts of the state at once.
const reducer = (state,action) => {
switch (action.type){
case "loading":
return {
...state,
loading: true,
data: null,
authorized: false
title: "Loading..."
};
default:
break;
}
}
While most of the stuff you can do with useReducer can be done with useState, useReducer may be much neater in some cases.