DEV Community

Mahalakshmi C
Mahalakshmi C

Posted on

useCallback, useMemo, and useReducer in React

React provides several Hooks to manage state, optimize performance, and organize component logic.

1. useCallback Hook

What is useCallback?

useCallback is a React Hook that caches a function definition between renders until its dependencies change.

It is useful when we want to avoid creating a new function reference on every render, especially when passing callbacks to memoized child components.

Syntax

const cachedFunction = useCallback(() => {
    // function logic
}, [dependencies]);
Enter fullscreen mode Exit fullscreen mode
  • Callback function: The function we want to cache.
  • Dependency array: Values that the function depends on.
  • When a dependency changes, React returns a new function definition.

Example

import { useState, useCallback } from "react";

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

    const showMessage = useCallback(() => {
        console.log("Button clicked");
    }, []);

    return (
        <div>
            <h2>Count: {count}</h2>

            <button onClick={() => setCount(count + 1)}>
                Increase
            </button>

            <button onClick={showMessage}>
                Show Message
            </button>
        </div>
    );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

How does it work?

  1. useCallback caches the showMessage function.
  2. The empty dependency array means the function reference remains cached across renders, provided the component remains mounted.
  3. Clicking the Increase button changes the state and re-renders the component.
  4. React can reuse the cached function reference.

Important: useCallback does not prevent a component from re-rendering by itself. It is most useful when function identity matters, such as when passing a callback to a child wrapped in React.memo.

Why do we use useCallback?

  • To preserve function references between renders.
  • To help optimize memoized child components.
  • To avoid unnecessary effect re-runs caused by changing function dependencies.

2. useMemo Hook

What is useMemo?

useMemo is a React Hook that caches the result of a calculation between renders until its dependencies change.

It is useful when a calculation is expensive and does not need to be repeated when its inputs remain the same.

Syntax

const cachedValue = useMemo(() => {
    return calculateValue();
}, [dependencies]);
Enter fullscreen mode Exit fullscreen mode
  • Callback function: Contains the calculation.
  • Dependency array: Contains the values used by the calculation.
  • Return value: The calculated result, which React can reuse while the dependencies remain unchanged.

Example

import { useState, useMemo } from "react";

function App() {
    const [number, setNumber] = useState(5);
    const [count, setCount] = useState(0);

    const square = useMemo(() => {
        console.log("Calculating square");
        return number * number;
    }, [number]);

    return (
        <div>
            <h2>Number: {number}</h2>
            <h2>Square: {square}</h2>
            <h2>Count: {count}</h2>

            <button onClick={() => setNumber(number + 1)}>
                Change Number
            </button>

            <button onClick={() => setCount(count + 1)}>
                Increase Count
            </button>
        </div>
    );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

How does it work?

Initially, number is 5, so the square is 25.

When the Increase Count button is clicked, count changes, but number remains the same. React can reuse the cached square value instead of recalculating it.

When the number changes, React recalculates the square.

Why do we use useMemo?

  • To cache expensive calculation results.
  • To avoid unnecessary recalculations.
  • To help optimize rendering when calculations are costly.

Important: Do not use useMemo for every calculation. Simple calculations usually do not need it. React treats memoization as an optimization, not a guarantee.


3. useReducer Hook

What is useReducer?

useReducer is a React Hook used to manage state through a reducer function and actions.

It is useful when state logic becomes complex or when several actions need to update the same state.

Syntax

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

useReducer returns an array containing two values:

  • state — the current state.
  • dispatch — a function used to send an action to the reducer.

Important Terms

Reducer function: Receives the current state and an action, then returns the next state.

Action: An object that describes what should happen.

Dispatch: Sends an action to the reducer.

Initial state: The starting state value.

Example: Counter

import { useReducer } from "react";

function reducer(state, action) {
    switch (action.type) {
        case "increase":
            return { count: state.count + 1 };

        case "decrease":
            return { count: state.count - 1 };

        case "reset":
            return { count: 0 };

        default:
            return state;
    }
}

function App() {
    const initialState = { count: 0 };

    const [state, dispatch] = useReducer(
        reducer,
        initialState
    );

    return (
        <div>
            <h2>Count: {state.count}</h2>

            <button onClick={() => dispatch({ type: "increase" })}>
                Increase
            </button>

            <button onClick={() => dispatch({ type: "decrease" })}>
                Decrease
            </button>

            <button onClick={() => dispatch({ type: "reset" })}>
                Reset
            </button>
        </div>
    );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

How does it work?

  1. The initial state is { count: 0 }.
  2. Clicking Increase calls dispatch({ type: "increase" }).
  3. The reducer receives the current state and the action.
  4. The reducer returns a new state object.
  5. React updates the state and re-renders the component.

Why do we use useReducer?

  • To organize complex state logic.
  • To handle multiple types of state updates.
  • To keep state transitions in one reducer function.
  • To manage related state values together.

For example, useReducer can be useful in a shopping cart, form management, or a task management application.


Difference Between useCallback, useMemo, and useReducer

Hook Main purpose Returns
useCallback Caches a function definition Cached function
useMemo Caches a calculation result Cached value
useReducer Manages state using actions and a reducer Array containing state and dispatch

Conclusion

useCallback and useMemo help optimize performance when caching is useful. useReducer helps manage state updates through a structured reducer function. Understanding these Hooks makes it easier to build React applications that are organized, maintainable, and efficient.

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.