The Great Hook Showdown: useState 🆚 useReducer

Udit Kumar's Avatar

Udit Kumar / February 08, 2022

3 min read • ––– views

Banner Image

Hey 👋 there React enthusiasts! Are you tired 😩 of trying to decide whether to use useState or useReducer in your components? Well, have no fear because I'm here to help you make that decision 🤙.

First things first, let's define these two hooks. useState is a hook that allows you to add state to functional components. It returns an array with two items: the current state value and a function to update it. On the other hand, useReducer is also a hook that allows you to add state to functional components, but it takes in a reducer function and returns the current state and a dispatch function.

Now, the question is: when should you use useState and when should you use useReducer?

Meme gif

Well, the general rule of thumb is that if you have simple state logic, then you should use useState. For example, if you just need to keep track of a boolean value or a string, useState is the way to go.

For example, let's say you want to keep track of whether a user is logged in or not. You can do this by using useState:

jsx
import React, { useState } from 'react'; const App = () => { const [isLoggedIn, setIsLoggedIn] = useState(false); return ( <div> <button onClick={() => setIsLoggedIn(!isLoggedIn)}> {isLoggedIn ? 'Log out' : 'Log in'} </button> </div> ); };

On the other hand, if you have complex state logic that requires multiple updates or performing calculations based on the previous state, then useReducer is the hook for you. It's like a mini Redux store within your component, allowing you to manage your state more efficiently.

Like if you want to keep track of a user's shopping cart. You can do this by using useReducer:

jsx
import React, { useReducer } from 'react'; const initialState = { items: [], total: 0 }; const reducer = (state, action) => { switch (action.type) { case 'ADD_ITEM': return { ...state, items: [...state.items, action.payload], total: state.total + action.payload.price }; case 'REMOVE_ITEM': return { ...state, items: state.items.filter((item) => item.id !== action.payload.id), total: state.total - action.payload.price }; default: return state; } }; const App = () => { const [state, dispatch] = useReducer(reducer, initialState); return ( <div> <button onClick={() => dispatch({ type: 'ADD_ITEM', payload: { id: 1, price: 10 } }) } > Add item </button> <button onClick={() => dispatch({ type: 'REMOVE_ITEM', payload: { id: 1, price: 10 } }) } > Remove item </button> </div> ); };

But wait, there's more! If you find yourself using multiple useState calls to manage your state, it might be a good idea to consider using useReducer instead. This is because useReducer allows you to centralize your state updates in a single function, making your code more organized and easier to read.

So, to sum it up: useState for simple state updates and useReducer for complex state logic and multiple updates.

But remember, these are just general guidelines. The most important thing is to choose the hook that best fits your needs and makes your code more readable and maintainable.

And that's it, folks! I hope this helps you make the right decision when it comes to useState vs useReducer. Happy coding!

If you have any questions or comments, feel free to reach out to me on Twitter or LinkedIn. I'd love to hear from you!

• Author Github Profile