Mahamudul Hasan Rubel
HomeBlogCoursesAboutProjectsSkillsExperiencePhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • Blog
  • Courses
  • About
  • Projects
  • Skills
  • Experience
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 13 of the Intermediate React: Hooks, State & Data Patterns course
ReactJune 25, 20263 min read

Structuring State for Performance: Optimizing React Context

Stop React performance bottlenecks caused by the Context API. Learn how to split contexts, memoize values, and prevent unnecessary re-renders in your app.

ReactPerformanceContext APIHooksOptimizationjavascriptfrontend

Previously in this course, we explored Architecting Global State with Context and Reducer to centralize our application logic. While this pattern is powerful, it introduces a common performance trap: whenever the context value changes, every single component consuming that context re-renders, regardless of whether it actually needs the updated data.

In this lesson, we’ll tackle this performance overhead by splitting our contexts and memoizing values to ensure your dashboard remains snappy as it grows.

The Problem: Context as a Performance Bottleneck

When you provide an object as a context value, React performs a reference equality check. If your provider component re-renders (perhaps due to a parent component updating), it creates a new object reference. Every consumer—even those only using a small fraction of the state—will re-render.

If your state object contains both high-frequency updates (like a search input) and low-frequency data (like user preferences), your entire UI tree becomes inefficient.

Strategy 1: Splitting Contexts

The most effective way to optimize is to separate state that changes at different rates. Instead of one "God Context" that holds everything, create smaller, specialized providers.

For our dashboard, we’ll split our state into DashboardData and DashboardSettings.

JSX
const DashboardDataContext = createContext();
const DashboardSettingsContext = createContext();

export const DashboardProvider = ({ children }) => {
  const [data, setData] = useState(/* ... */);
  const [settings, setSettings] = useState(/* ... */);

  return (
    <DashboardDataContext.Provider value={data}>
      <DashboardSettingsContext.Provider value={settings}>
        {children}
      </DashboardSettingsContext.Provider>
    </DashboardSettingsContext.Provider>
  );
};

By splitting these, a change to settings will not trigger a re-render in components that only consume data.

Strategy 2: Memoizing Context Values

Even with split contexts, you must ensure the object passed to the value prop is memoized. If the provider itself re-renders, a new object is created unless you use useMemo.

We already discussed Memoizing Expensive Calculations with useMemo for performance earlier in this course; here, we apply it to the provider value itself.

JSX
const DashboardProvider = ({ children }) => {
  const [data, setData] = useState({ items: [] });
  const [settings, setSettings] = useState({ theme: CE9178">'dark' });

  // Memoize the data object
  const dataValue = useMemo(() => ({ data, setData }), [data]);
  
  // Memoize the settings object
  const settingsValue = useMemo(() => ({ settings, setSettings }), [settings]);

  return (
    <DashboardDataContext.Provider value={dataValue}>
      <DashboardSettingsContext.Provider value={settingsValue}>
        {children}
      </DashboardSettingsContext.Provider>
    </DashboardDataContext.Provider>
  );
};

Hands-on Exercise: Refactor the Dashboard

  1. Identify two pieces of state in your current dashboard project that update at different frequencies.
  2. Create two separate Contexts for these states.
  3. Wrap your application in both Providers.
  4. Use useMemo to stabilize the value passed to each provider.
  5. In a consumer component, use useContext to hook into only the specific context you need.

Common Pitfalls

  • Over-splitting: Don't create a context for every single variable. If two values always change together, keep them in the same context.
  • Forgetting useMemo: Even if you split contexts, if the provider component re-renders and you haven't memoized the value, you are still triggering re-renders in all consumers.
  • Ignoring React.memo: For leaf components that consume context, use React.memo as a secondary line of defense to ensure they only re-render if their props or context values actually change.

Recap

We've moved beyond basic state sharing to professional-grade performance management. By splitting contexts by update frequency and memoizing the values, we prevent the "ripple effect" of re-renders that plagues poorly architected React applications. This is critical for maintaining the high-performance bar we set when we first started Introduction to Context API: Avoiding Prop Drilling in React.

Up next: We will apply these patterns to handle authentication state, ensuring our security layer doesn't slow down our UI.

Previous lessonImplementing Theme ContextNext lesson Handling Authentication State
Back to Blog

Similar Posts

ReactJune 25, 20264 min read

Implementing Theme Context: A Global Toggle for React Dashboards

Learn to build a production-ready theme system using the Context API and useReducer. Master global state for light/dark mode in your React dashboard.

Read more
ReactJune 25, 20263 min read

Introduction to Context API: Avoiding Prop Drilling in React

Learn how to use the Context API and useContext to share data across your React application, effectively eliminating prop drilling for cleaner code.

Part of the course

Intermediate React: Hooks, State & Data Patterns

intermediate · Lesson 13 of 48

  1. 1

    Mastering useRef for DOM Access

    4 min
  2. 2

    Persistent Mutable Values with useRef

    4 min
  3. 3

    Memoizing Expensive Calculations with useMemo

    3 min
Read more
ReactJune 25, 20263 min read

Integrating Reducers with Auth State: A Robust Pattern

Master authentication state management by integrating useReducer. Learn to handle loading, errors, and token logic for a secure, predictable React flow.

Read more
4

Optimizing Function References with useCallback

3 min
  • 5

    Introduction to Custom Hooks

    4 min
  • 6

    Building a useLocalStorage Hook

    4 min
  • 7

    Refactoring Dashboard Settings

    4 min
  • 8

    Complex State with useReducer

    3 min
  • 9

    Managing Object-Based State

    3 min
  • 10

    Introduction to Context API

    3 min
  • 11

    Architecting Global State with Context and Reducer

    3 min
  • 12

    Implementing Theme Context

    4 min
  • 13

    Structuring State for Performance

    3 min
  • 14

    Handling Authentication State

    3 min
  • 15

    Integrating Reducers with Auth State

    3 min
  • 16

    Introduction to React Router

    3 min
  • 17

    Dynamic Routing with URL Parameters

    3 min
  • 18

    Nested Routes and Layouts

    4 min
  • 19

    Protected Routes for Authenticated Views

    Coming soon
  • 20

    Programmatic Navigation

    Coming soon
  • 21

    Building the Dashboard Navigation Structure

    Coming soon
  • 22

    Asynchronous Data Lifecycle

    Coming soon
  • 23

    Caching Strategies with React Query

    Coming soon
  • 24

    Mutations and Data Updates

    Coming soon
  • 25

    Synchronizing Client and Server State

    Coming soon
  • 26

    Integrating Live Data into the Dashboard

    Coming soon
  • 27

    Error Handling and Loading UI

    Coming soon
  • 28

    Controlled vs Uncontrolled Components

    Coming soon
  • 29

    Real-time Form Validation

    Coming soon
  • 30

    Schema-based Validation with Zod

    Coming soon
  • 31

    Handling Multi-step Forms

    Coming soon
  • 32

    Optimizing Form Submissions

    Coming soon
  • 33

    Performance Profiling with React DevTools

    Coming soon
  • 34

    Refactoring for Scalability

    Coming soon
  • 35

    Finalizing Dashboard Data Flow

    Coming soon
  • 36

    Deploying the Application

    Coming soon
  • 37

    Advanced Hook Composition

    Coming soon
  • 38

    Implementing Middleware for State

    Coming soon
  • 39

    Advanced Context Patterns

    Coming soon
  • 40

    Router Loaders and Data Prefetching

    Coming soon
  • 41

    Complex Route Guards

    Coming soon
  • 42

    Handling Large Datasets in UI

    Coming soon
  • 43

    Testing Hooks and Components

    Coming soon
  • 44

    Managing Global Modals

    Coming soon
  • 45

    Implementing Keyboard Shortcuts

    Coming soon
  • 46

    Optimizing Asset Loading

    Coming soon
  • 47

    Internationalization Basics

    Coming soon
  • 48

    Managing WebSocket Connections

    Coming soon
  • View full course