What does the "selector pattern" do in context?
The problem it solves
A regular context works like this:
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:
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 inuserorcart."
Example with the use-context-selector library
This library implements the selector pattern for the Context API.
1. Create the context
import { createContext } from "use-context-selector";
export const AppContext = createContext({
user: { name: "Tim" },
theme: "light",
cart: [],
});2. Wrap the Provider
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
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
themechanges, onlyThemeSwitcherre-renders; - When
userchanges, onlyUserNamedoes; - Other consumers are left untouched.
Why this works
- Each consumer subscribes to a specific sub-value from the context.
- Under the hood,
use-context-selectorcreates a "mini-subscription" to only the selected fragment ofvalue. - 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:
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
| Approach | Behavior |
|---|---|
useContext | The component is subscribed to the whole value, it re-renders on any change |
use-context-selector | The 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 readyA concise answer to help you respond confidently on this topic during an interview.