DEV Community

loading...

Understanding useReducer in react

Elizabeth
I am a frontend developer, and I write react.js code these days. I am hoping to share my knowledge with others. she/her
ใƒป3 min read

Hi there, in my last post we covered useCallback in react, and now, we'll be looking at one last hook provided to us by the amazing React team: useReducer

What is the useReducer hook?

Before we continue to explain what the hook is all about let's take a step back and look at what a reducer is.

What is a reducer

If you are familiar with redux then you'd know what a reducer function is.

A reducer accepts a state and an action as an argument and returns a new state as a result. Here's a common example of a reducer

const initialState = {
    loading: false,
    error: false,
    names: [],
};

const reducer = (state = initialState, action) => {
  switch(action.type) {
    case "loading":
      return { ...state, loading: true };
    case "error":
      return { ...state, error: true, loading: false };
    case "success":
      return { ...state, names: action.payload };
    default:
      return state;
  }
}
Enter fullscreen mode Exit fullscreen mode

What is going on here?
The function above is checking for a type and returning a state based on the type that was passed.

Back to useReducer

The useReducer hook is very similar to the useState hook, it allows you to manage a state and rerender the component whenever your state changes, It accepts a reducer and an initial state (like the example above) and returns a new version of the state and a dispatch method based on the action performed in the reducer.

Here is an example of how it is being used:

const [state, dispatch] = useReducer(reducer, initialState);
Enter fullscreen mode Exit fullscreen mode

The hook also takes a third argument that will lazily initialize the state or reset the state back to its initial state. You can read more on the lazy initialization in react documentation

const [state, dispatch] = useReducer(reducer, initialState, initFunc);
Enter fullscreen mode Exit fullscreen mode

Why should I use this?

The useReducer hook is often used when you have a complex state, or where the initial state is dependent on another state.

To understand this better, we need some actions.

film scene gif

Examples

Let us look at a counter using useState

const [num1, setNum1] = useState(0);

  const decrement = () => {
    setNum1((prev) => prev - 1);
  };
  const increment = () => {
    setNum1((prev) => prev + 1);
  };

  return (
    <div className="App">
      Num: {num1}
      <div className="grid">
        <button className="box" onClick={increment}>
          +
        </button>
        {num1 ? (
          <button className="box" onClick={decrement}>
            -
          </button>
        ): (<div />)}
      </div>
    </div>
  );
Enter fullscreen mode Exit fullscreen mode

Now let's look at the same example using useReducer

import { useReducer } from "react";
const initialState = { num: 0 };

function reducer(state, action) {
  switch (action.type) {
    case "increment":
      return { num: state.num + 1 };
    case "decrement":
      return { num: state.num - 1 };
    default:
      throw new Error();
  }
}
export default function App() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div className="App">
      <div>Num: {state.num}</div>
      <div className="grid">
        <button className="box" onClick={() => dispatch({ type: "increment" })}>
          +
        </button>
        {state.num ? (
          <button className="box" onClick={decrement}>
            -
          </button>
        ): (<div />)}
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In our reducer function, we're using the type to determine what action will be performed on the state.

This method is better if we're creating a calculator for example.

Conclusion

There's been a lot of arguments on whether to use the useState hook or useReducer, it actually depends on what you're doing but Kent C. Dodds gave very detailed examples on when to use either in his post.

Thank you so much for reading, In my next post we'll be looking at how to create our very own react hook.

If you have any questions or comments please drop them in the comment below. Don't forget to stay safe and keep being amazing.

Discussion (2)

Collapse
marcosnto profile image
Marcos Neto

Hi! In the last example you miss to change the onClick for decrement. Thank you for those articles, helped me alot!

Collapse
ilizette profile image
Elizabeth Author

Thanks you for pointing that out.

Thanks for reading, I'm really glad it helped you