Introduction This hook comes under the additional section of hooks and serves as an alternative to useState hook [explained in the previous posts]. useReducer is preferable to useState when we have complex state logic that involves multiple sub-values or when the next state depends on the previous one. useReducer hook updates the complex state by passing actions rather than calling an updater function like useState.
Implementation of useReducer hook The useReducer hook accepts a reducer of type (state, action) => newState, and returns the current state paired with a dispatch method. It performs just like the reducer in Redux. Below is the snippet containing the syntax.
const state = {
age: 0,
error: null
};
const [initialState, dispatch] = useReducer(ageReducer, state);
In the above snippet, the useReducer hook takes in an initialState, and a reducer ageReducer. The initialState is initialized with the state object passed inside the useReducer hook. We pass this initialState and the dispatch in the context Provider object[explained in the previous post]. Below is a snippet of the ageReducer which is passed in the useReducer hook.
import { actionTypes } from '../actions/ActionTypes';
const ageReducer = (state, action) => {
let newState;
let newValue;
const { type, payload } = action;
debugger;
switch (type) {
case actionTypes.increase_age:
newValue = parseInt(payload, 10 ) + 1;
newState = { ...state, age: newValue, error: null };
break;
case actionTypes.decrease_age:
newValue = payload - 1;
newState = { ...state, age: newValue, error: null };
break;
case actionTypes.invalid_age:
newState = { ...state, error: "Age can't be smaller than 0" };
break;
default:
newState = { ...state };
break;
}
return newState;
};
export default ageReducer;
Everytime a button is clicked or any event is triggered, the dispatch method[to know about dispatch--click here], which is fetched by the contextConsumer, is invoked. Below is a snippet on how dispatch from the context object is used.
<button
data-testid="button1"
className='btn btn-dark'
onClick={() => agecontext.dispatch(actions.increment_age(agecontext.age))}
>
In the above snippet, ageContext is the context object initialized by consuming the context inside a React functional component. The dispatch method inside the ageContext is invoked on the onClick event of a button. This dispatches an action and the action is now matched in the ageReducer which was passed as a parameter inside the useReducer hook. If the action matches any of the actions mentioned in the ageReducer, the newState is returned and the state object is updated by the useReducer hook. If we return the same value from a Reducer Hook as the current state, React will bail out without rendering the children or firing the useEffect hook. React may re-render a parent component but won't do a deep dive in the tree if the current state and the initial state produced by the useReducer are same.
Summary In this post, we have discussed about the useReducer hook. We also saw where we should use it and how to use it. We saw how this hook updates the complex state and how it automatically avoids unnecessary re-rendering.
Comments