Skip to main content

What does the "selector pattern" do in context?

The problem it solves

A regular context works like this:

javascript
const AppContext = createContext({ user, theme, cart }); const value = { user, theme, cart }; // the object changes by reference <AppContext.Provider value={value}> <Child /> </AppContext.Provider>

If inside Child you read only theme:

javascript
const { theme } = useContext(AppContext);

then when user or cart changes, theme stays the same, but the component still re-renders, because value changed by reference.

This is a fundamental behavior of React Context. Even if only one part changed, all consumers re-render.


Selector pattern: how it solves this

The idea: a component subscribes only to part of the context, not the whole value object.

In other words:

"Watch only theme, and do not react to changes in user or cart."


Example with the use-context-selector library

This library implements the selector pattern for the Context API.

1. Create the context

javascript
import { createContext } from "use-context-selector"; export const AppContext = createContext({ user: { name: "Tim" }, theme: "light", cart: [], });

2. Wrap the Provider

javascript
import { AppContext } from "./AppContext"; export function AppProvider({ children }) { const [user, setUser] = useState({ name: "Tim" }); const [theme, setTheme] = useState("light"); const [cart, setCart] = useState([]); const value = { user, theme, cart, setUser, setTheme, setCart }; return <AppContext.Provider value={value}>{children}</AppContext.Provider>; }

3. Use selectors in consumers

javascript
import { useContextSelector } from "use-context-selector"; import { AppContext } from "./AppContext"; function ThemeSwitcher() { const theme = useContextSelector(AppContext, ctx => ctx.theme); const setTheme = useContextSelector(AppContext, ctx => ctx.setTheme); console.log("ThemeSwitcher render"); return ( <button onClick={() => setTheme(theme === "light" ? "dark" : "light")}> {theme} </button> ); } function UserName() { const user = useContextSelector(AppContext, ctx => ctx.user); console.log("UserName render"); return <p>Hello, {user.name}</p>; }

Now:

  • When theme changes, only ThemeSwitcher re-renders;
  • When user changes, only UserName does;
  • Other consumers are left untouched.

Why this works

  • Each consumer subscribes to a specific sub-value from the context.
  • Under the hood, use-context-selector creates a "mini-subscription" to only the selected fragment of value.
  • When the context updates, React compares the old and new selected value with Object.is, and if they are equal, the component does not re-render.

Without third-party libraries (a basic implementation)

You can implement the selector approach manually by splitting the contexts:

javascript
export const UserContext = createContext(); export const ThemeContext = createContext(); export const CartContext = createContext();

and consuming exactly the one you need.

This is the simplest equivalent of the "selector pattern", just not at the value level, but at the level of "context as an entity".


Summary

ApproachBehavior
useContextThe component is subscribed to the whole value, it re-renders on any change
use-context-selectorThe component is subscribed to the selected field, it re-renders only when that changes
"Many contexts"Each has its own area of responsibility, also a variant of the selector pattern

The selector pattern helps:

reduce re-renders on frequent context updates improve the performance of large component trees write flexible, reactive contexts without heavy stores (Redux, Zustand)

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.