Let's have a look at an advanced hook in the React series.
useReducer Hook
This is one of the hooks that can be considered as advanced React.
We use this hook when we have a more complicated setup as far as states are concerned.
It is similar to useState hook but a bit more advanced than its predecessor. The hook helps us in creating or providing more structure to the state.
Some common practise includes that we declare reducer as
const [state, dispatch]= useReducer(reducer, defaultState)
The default state is the initial value passed along with the reducer can be of any type or a combination of types.
Now whenever we need to do something with the state it must, must use the 'dispatch' and it goes through the 'reducer'.
The reducer function takes the old state and an action to return the new state.
const [people, setPeople] = useState([])
const [isModalOpen, setIsModalOpen] = useState(false)
const [modalContent, setModalContent] = useState('')
The above code written using the useState hook can be condensed using the useReducer hook
const deafaultState = {
people: [],
isModalOpen: false,
modalConten: ""
}
const [state, dispatch] = useReducer(reducer, defaultState)
While calling the dispatch function we 'always' need to pass an object with the property name of "type". The object is called the action.
The common practice while the passing type is using uppercase. For example:
{type: "TESTING"}
From the reducer we always, always must return some kind of state. To do that we need something called a payload.
Payload is a property of action which holds the content of the message of the action. You can think of it as the content or message of an email. I think of it as the payload in fighter jets xD.
Type is the type of action being sent. Think of it as the subject of the email. I think of it as the type of TNT in the payload.
One last thing to keep in mind is to always keep track of the old states while dealing with the actions in the reducer function.
Let's have a look at a simple counter program made using the hook.
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
Do let me know your thoughts and follow my Twitter and LinkedIn.
Top comments (2)
useReducer
is an implementation of the flux pattern within react fiber. This pattern can be advantageous if your state changes are naturally expressed as actions and your selectors are fine-grained enough only to catch useful changes. In most cases though, the additional boilerplate code for the actions is redundant and won't increase maintainability.Thanks for the insight Alex. I will definitely keep that in mind