how to useReducer

how to useReducer

1. Definition

useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values or when the next state depends on the previous one.

It accepts a reducer of type (state, action) => newState, and returns the current state paired with a dispatch method. (If you’re familiar with Redux, you already know how this works.

Here is the countReducer example;

const initialState = { count: 0 }

const counterReducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

2. Specifying the initial State

There are two ways to initialized the useReducer state;

2.1. Basic

We can just give it as a second argument to useReducer call;

const [state, dispatch] = useReducer(
  countReducer,
  { count: 0 } // second argument
);

2.2. Lazy Initialization

We can also initialize it lazily by giving it as a third parameter as a function;

const initState = (defaultCount) => ({ count: defaultCount })

const Counter = ({ counter }) => {
    const [state, dispatch] = useReducer(
      countReducer,
      counter, // second argument
        initState // third argument
    );

    // Rest of the component...
}

3. Usage

After we initialize it we just need to call dispatch functions that we are getting from useReducer hook and use it as a handler inside our elements.

React guarantees that dispatch function identity is stable and won’t change on re-renders.

const Counter = ({ counter }) => {
    const [state, dispatch] = useReducer(countReducer, 0);

    return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}