React Mastery / Advanced React Hooks

Context with useMemo Hook

In React Context, useMemo is used to prevent unnecessary re-renders of consumer components.

By default, every time a Provider’s parent component re-renders, the value object in the Provider is recreated. Even if the data inside hasn't changed, React sees a "new" object (a different reference in memory) and forces every component using that context to re-render.


❓Where to apply useMemo

You should apply useMemo directly to the value object you are passing into the Provider.

The Problem (Without useMemo)

In this example, every time App re-renders (e.g., due to a unrelated state change), the value object is brand new, triggering all consumers to update.

// BAD: New object created on every render
const value = { user, theme }; 

return (
  <AuthContext.Provider value={value}>
    {children}
  </AuthContext.Provider>
);

The Solution (With useMemo)

By wrapping the object in useMemo, React will only create a new object if the dependencies (user or theme) actually change.

import { useMemo, useState } from 'react';

export function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  const [theme, setTheme] = useState('dark');

  // React "remembers" this object unless user or theme changes
  const memoizedValue = useMemo(() => ({
    user,
    theme
  }), [user, theme]); 

  return (
    <AuthContext.Provider value={memoizedValue}>
      {children}
    </AuthContext.Provider>
  );
}

👉 When is it absolutely necessary?

Scenario

Do you need useMemo?

Why?

Passing a primitive

No

Strings or numbers (e.g., value="dark") are compared by value, not reference.

Passing an object

Yes

Objects {} are compared by reference. A new {} is never equal to the old {}.

Passing an array

Yes

Arrays [] are also compared by reference.

Frequent Parent Renders

Critical

If the Provider's parent updates often, your entire app will lag without memoization.


Summary of Logic

  1. Identify the dependencies: What variables actually change the context? (e.g., user).

  2. Wrap the value: Put your object/array inside useMemo.

  3. Define the array: Ensure all variables used inside the object are listed in the useMemo dependency array.

Note: If you are passing functions (like login or toggleTheme), you should also wrap those functions in useCallback before putting them into the useMemo object to ensure their references remain stable as well.