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

Subscribe to the newsletter

Get new articles and course lessons delivered to your inbox. No spam, unsubscribe anytime.

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 8 of the Advanced React: Performance, Architecture & Patterns course
ReactJune 27, 20264 min read

Advanced Context Composition: High-Performance State Selectors

Master Context Selector hooks to prevent unnecessary re-renders. Learn how to implement granular state subscriptions and optimize your React architecture today.

ReactContext APIPerformanceHooksArchitecturejavascriptfrontend

Previously in this course, we explored Optimizing Context Providers: Scaling React Performance and Structuring State for Performance: Optimizing React Context. Those lessons focused on splitting contexts and memoizing values to stop the "re-render cascade."

In this lesson, we take a leap forward. We will move beyond simply "fixing" providers and instead build an architecture where components subscribe only to the specific slices of state they need, effectively bypassing the limitations of the standard Context API.

The Problem: The "All or Nothing" Subscription

When you consume a context via useContext(MyContext), your component subscribes to the entire value object. If that context provider holds a large object (e.g., a complex user profile or a global configuration), any change to any property within that object forces every consuming component to re-render.

Even if you memoize the provider value using useMemo as discussed in React Re-render Optimization: Mastering useMemo vs useCallback, you are still bound by the identity of the object. If the object changes, the component re-renders.

The Selector Pattern Architecture

To solve this, we implement a Selector Hook. Instead of consuming the context directly in your UI components, you create a custom hook that accepts a selector function. This hook uses useSyncExternalStore or a combination of useRef and useEffect to decide whether the component should actually trigger a render.

Worked Example: Building a Context Selector

Let's refactor a global SettingsContext that manages a large user preference object.

1. The Provider Setup

First, we split our state and dispatch functions. This prevents UI components that only need to read data from re-rendering when the setter function identity changes.

JAVASCRIPT
const SettingsStateContext = createContext(null);
const SettingsDispatchContext = createContext(null);

export const SettingsProvider = ({ children }) => {
  const [state, setState] = useState({ theme: CE9178">'dark', notifications: true, lang: CE9178">'en' });
  
  // Use useMemo to prevent re-renders when the provider itself re-renders
  const dispatch = useMemo(() => (action) => {
    setState(prev => ({ ...prev, ...action }));
  }, []);

  return (
    <SettingsDispatchContext.Provider value={dispatch}>
      <SettingsStateContext.Provider value={state}>
        {children}
      </SettingsStateContext.Provider>
    </SettingsDispatchContext.Provider>
  );
};

2. The Selector Hook

Now, we create a hook that allows components to subscribe only to specific changes.

JAVASCRIPT
export function useSettingsSelector(selector) {
  const state = useContext(SettingsStateContext);
  if (!state) throw new Error("useSettingsSelector must be used within SettingsProvider");

  // We use useMemo to hold the selected value
  // The component only re-renders if the result of the selector changes
  return useMemo(() => selector(state), [state, selector]);
}

3. Consuming with Granularity

Now, a component that only cares about the theme will ignore changes to notifications or lang.

JAVASCRIPT
const ThemeButton = () => {
  // This component will ONLY re-render if CE9178">'theme' changes
  const theme = useSettingsSelector(state => state.theme);
  
  return <button>Current theme: {theme}</button>;
};

Advanced Component-Level Updates

In our project, we are currently managing the dashboard state via a single monolith. To advance our project, we will now apply this selector pattern to our DashboardData context, allowing the sidebar and the main chart to update independently despite sharing the same data source.

Hands-on Exercise

  1. Identify a "heavy" context in your current project that causes tree-wide re-renders.
  2. Implement a useSelector hook for this context.
  3. Use the React DevTools Profiler to verify that a change in one property no longer triggers a re-render in components that do not select that property.

Common Pitfalls

  • Selector Stability: If you pass an anonymous function to your selector hook (e.g., useSettingsSelector(s => s.theme)), that function is recreated on every render. If your hook uses that function in a dependency array, it will trigger unnecessary re-renders. Always wrap your selector in useCallback if it's passed as a dependency, or ensure your hook implementation is optimized to handle fresh function references.
  • The "Double Render" Trap: When implementing custom subscription logic, ensure you aren't triggering renders during the render phase. Always use useSyncExternalStore for external state or keep your subscription logic strictly within hooks that respect React's rendering lifecycle.
  • Over-Engineering: Not every context needs a selector. If your context is small or rarely updates, standard useContext is perfectly fine. Don't introduce the complexity of selectors unless you have a performance bottleneck identified via Profiling with React DevTools.

Recap

Context composition via selectors allows us to decouple our UI components from the shape of our global state. By using custom hooks to subscribe to specific slices of data, we achieve a level of granular performance previously only available through external state management libraries like Redux or Zustand.

Up next: We will explore how to eliminate prop drilling entirely by combining these patterns with sophisticated component composition.

Previous lessonOptimizing Context ProvidersNext lesson Eliminating Prop Drilling
Back to Blog

Similar Posts

ReactJune 27, 20264 min read

Eliminating Prop Drilling: Architecture, Composition, and Context

Learn to eliminate prop drilling in React using component composition and the Context API to build cleaner, more maintainable, and highly scalable architectures.

Read more
ReactJune 27, 20264 min read

Optimizing Context Providers: Scaling React Performance

Learn to prevent tree-wide re-renders in your React application by optimizing Context Providers through value memoization, state splitting, and selective hooks.

Part of the course

Advanced React: Performance, Architecture & Patterns

advanced · Lesson 8 of 47

  1. 1

    Deep Dive into the Reconciliation Algorithm

    4 min
  2. 2

    Profiling with React DevTools

    3 min
  3. 3

    Establishing Performance Budgets

    3 min
Read more
ReactJune 26, 20263 min read

Advanced Context Patterns: Scalable State for React Dashboards

Stop the "provider hell" and performance bottlenecks. Learn advanced context patterns to manage large-scale state trees and optimize your React architecture.

Read more
  • 4

    Strategic use of React.memo

    3 min
  • 5

    Mastering useCallback and useMemo

    4 min
  • 6

    State Colocation Strategies

    4 min
  • 7

    Optimizing Context Providers

    4 min
  • 8

    Advanced Context Composition

    4 min
  • 9

    Eliminating Prop Drilling

    4 min
  • 10

    Introduction to Concurrent React

    4 min
  • 11

    Non-blocking UI with useTransition

    4 min
  • 12

    Handling Deferred Data with useDeferredValue

    3 min
  • 13

    Mastering Suspense for Data Fetching

    4 min
  • 14

    Streaming Server-Side Rendering

    3 min
  • 15

    Designing Compound Components

    3 min
  • 16

    The Render Props Pattern

    4 min
  • 17

    Implementing Control Props

    4 min
  • 18

    Headless UI Architectures

    3 min
  • 19

    Modular Directory Structures

    3 min
  • 20

    Refactoring Monolithic Components

    3 min
  • 21

    Optimistic UI Updates

    3 min
  • 22

    Advanced Cache Invalidation

    4 min
  • 23

    Handling Race Conditions

    4 min
  • 24

    Server-Client State Synchronization

    3 min
  • 25

    Route-level Code Splitting

    4 min
  • 26

    Offloading Tasks with Web Workers

    3 min
  • 27

    Advanced Error Boundaries

    3 min
  • 28

    Monitoring Production Performance

    4 min
  • 29

    Final Project Audit & Optimization

    Coming soon
  • 30

    Advanced Hook Patterns

    Coming soon
  • 31

    Managing Global State with Zustand/Redux

    Coming soon
  • 32

    Testing Performance-Critical Components

    Coming soon
  • 33

    Static Site Generation (SSG) Patterns

    Coming soon
  • 34

    Internationalization (i18n) Architecture

    Coming soon
  • 35

    Accessibility (a11y) in Advanced Components

    Coming soon
  • 36

    Managing Third-Party Integrations

    Coming soon
  • 37

    Advanced Form Handling

    Coming soon
  • 38

    Using Portals for UI Overlays

    Coming soon
  • 39

    Implementing Virtualized Lists

    Coming soon
  • 40

    Building Design System Primitives

    Coming soon
  • 41

    Managing Large-Scale Data Fetching

    Coming soon
  • 42

    Micro-Frontends with React

    Coming soon
  • 43

    Security Best Practices in React

    Coming soon
  • 44

    Advanced Ref Usage

    Coming soon
  • 45

    Memoization Pitfalls

    Coming soon
  • 46

    Mastering React Patterns for Scalability

    Coming soon
  • 47

    Advanced TypeScript with React

    Coming soon
  • View full course