Introduction
The useReducer
hook lets you use a reducer
in your component
const [state, dispatch] = useReducer(reducer, initialState)
What’s this dispatch
function?
The dispatch
function specifies how the state gets updated. It must be a pure function and should take an action
with a portion of the state
to update.
useReducer
returns an array containing the current state
and a dispatch
function:
import { useReducer } from "react";
//Note: state comes first then action in that order
function reducer(state, action) {
if (action.type === "increment_age") {
return {
age: state.age++,
name: state.name
};
}
}
function MyComponent() {
const [state, dispatch] = useReducer(reducer, { age: 29, name: "Naftali" });
const handleClick = () => {
dispatch({ type: "increment_age" });
};
return (
<>
<button onClick={handleClick}>Update Age</button>
<p>New age {state.age}</p>
<p>Name: {state.name}</p>
</>
);
}
export default function App() {
return (
<>
<MyComponent />
</>
);
}
A complete example can be found here
Caveats
The state
is immutable, any changes to the state will cause an error to be thrown. For objects and arrays, we return a copy of the state plus the newly updated portion of the state, for example in code:
For an array, our reducer becomes:
function reducer(state, action) {
if (action.type === "update_cart") {
return {
// copy over all state properties
...state,
// state is imutable so we return a copy of items plus our inserted item
items: [...state.items, action.item]
};
}
}
In the above reducer, we copy over the state
object using the spread operator and update the items
by copying the initial items [...state.items, action.item]
.
Doing state.items.push()
fails as we are mutating the state, push
method updates and changes(mutates) the underlying array
Found this article helpful? You may follow me on Twitter where I tweet about interesting topics on software development.