useState vs useReducer

useState vs useReducer

When to use each one?

First of all, it is necessary to understand the functionality of these hooks. In the next minutes, I try to summarize the principal functionalities for each one, and then describe their applications and recommendations.

useState


This hook permits us to add a state variable in our component, it returns a stateful value and a function to update that value, providing a simple way to introduce stateful logic into functional components.

This hook is typically used for managing simpler state needs within components.

Sintaxis

const [state, setState] = useState(initialValue);

initialValue : the value you want the state to be initially.

state : in the first render, it is equal to initialValue you have passed

setState : function to update value and trigger a re-render

Example:

The Counter changes when pressing the button, this action shoots an update function and changes the value state.

import { useState } from 'react'

export function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <span>Value count: {count}</span> 
      <button onClick={() => setCount(count + 1)}>
        +1
      </button>
    </div>
  )
}

useReducer


On the other hand, useReducer is used for managing complex state login within functional components. It takes in a reducer function and an initial state and returns the current state and a dispatch function to trigger state transitions.

Sintaxis

const [state, dispatch] = useReducer(reducer, initialValue, init?);

reducer : reducer function that specifies how the state gets updated

initialValue : value employed to initially calculate

init : this value is optional, it is an initializer function that should return the initial state

state : current state. In the first render, it is set with the initialValue or init

dispatch : the dispatch function updates the state to a different value and triggers a re-render

Example:

We modified the later example and now we use useReducer hook for changing the counter value in our component.

import { useReducer } from 'react';

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 (
    <div>
      <p>You clicked {state.count} times</p>
      <button onClick={() => dispatch({ type: 'increment' })}>
        Increment
      </button>
      <button onClick={() => dispatch({ type: 'decrement' })}>
        Decrement
      </button>
    </div>
  );
}

When to use each one?


useState is typically used for managing simpler state needs where the state transitions are straightforward and is good for managing independent pieces of state. It's simpler to use and understand, especially for beginners.

useReducer is often preferred when state management logic becomes more complex or when multiple actions need to be handled in a single stateful entity within a component.

💡
useReducer is inspired by Redux, a predictable state container for JavaScript apps, and it offers a similar API.

Recommendation


In some cases is necessary to use a useEffect hook when using these hooks to prevent re-renders in your project.