DEV Community

Abimanyu P
Abimanyu P

Posted on

Adavanced React Hooks

Advanced React Hooks

React provides several hooks to help developers manage complex state and optimize component performance. Three useful hooks are useReducer, useMemo, and useCallback. Although they serve different purposes, they help make React applications more predictable, efficient, and easier to maintain.

1. useReducer — Managing Complex State

The useReducer hook is an alternative to useState. It is especially useful when state updates involve multiple actions or complex logic.

Example: Counter using useReducer

import { useReducer } from "react";

function reducer(state, action) {
  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    case "decrement":
      return { count: state.count - 1 };
    case "reset":
      return { count: 0 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    <div>
      <h2>Count: {state.count}</h2>
      <button onClick={() => dispatch({ type: "increment" })}>
        Increment
      </button>
      <button onClick={() => dispatch({ type: "decrement" })}>
        Decrement
      </button>
      <button onClick={() => dispatch({ type: "reset" })}>
        Reset
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

How it works: The reducer function determines how the state changes based on an action. The dispatch function sends an action to the reducer, which returns the next state.

When to use it: Use useReducer when state has multiple related values, several update actions, or logic that becomes difficult to manage with multiple useState calls.

2. useMemo — Caching Expensive Calculations

The useMemo hook caches the result of a calculation between renders. React recalculates the value when one of its dependencies changes.

Example: Calculating a total

import { useMemo, useState } from "react";

function ShoppingCart() {
  const [price, setPrice] = useState(100);
  const [quantity, setQuantity] = useState(2);

  const total = useMemo(() => {
    console.log("Calculating total...");
    return price * quantity;
  }, [price, quantity]);

  return (
    <div>
      <h2>Total: ₹{total}</h2>
      <button onClick={() => setPrice(price + 10)}>
        Increase Price
      </button>
      <button onClick={() => setQuantity(quantity + 1)}>
        Increase Quantity
      </button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

How it works: React recalculates total when price or quantity changes. If the component renders again without either dependency changing, React can reuse the cached result.

When to use it: Use useMemo for expensive calculations or when maintaining a stable object or value can prevent unnecessary work. For simple calculations, it is usually unnecessary.

3. useCallback — Caching Function References

The useCallback hook caches a function reference between renders until its dependencies change. It is particularly useful when passing callbacks to memoized child components.

Example: Handling a button click

import { useCallback, useState } from "react";

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

  const increment = useCallback(() => {
    setCount((previous) => previous + 1);
  }, []);

  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={increment}>Increment</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

How it works: React reuses the same increment function reference across renders because its dependency list is empty. The functional state update ensures the callback uses the latest state without needing count as a dependency.

When to use it: Use useCallback when a stable function reference helps avoid unnecessary renders in memoized child components or when a function is a dependency of another hook. It is not necessary for every event handler.

Conclusion

These three React hooks solve different problems:

  • useReducer manages state transitions through a reducer function and dispatched actions.
  • useMemo caches the result of a calculation.
  • useCallback caches a function reference.

Understanding when to use each hook helps you write cleaner React code and optimize performance when necessary. However, these hooks are optimization and state-management tools, not requirements for every component. Start with simple solutions, measure performance when needed, and introduce advanced hooks where they provide a clear benefit.

Top comments (0)