gotchajavascriptreactModerate
React Context re-renders all consumers on any value change
Viewed 0 times
React 16.3+ for createContext
context re-renderscontext performanceuseMemo contextsplit contextcontext selector
browser
Problem
When a Context value changes, ALL components that consume that context re-render — even if they only use a part of the value that didn't change. This causes performance issues with large context objects.
Solution
Split context by update frequency, or use memoization:
// BAD: one giant context
const AppContext = createContext({ user, theme, settings, cart });
// Changing cart re-renders components that only use theme
// GOOD: split into separate contexts
const UserContext = createContext(null);
const ThemeContext = createContext('light');
const CartContext = createContext([]);
// GOOD: memoize context value
function Provider({ children }) {
const [user, setUser] = useState(null);
const value = useMemo(() => ({ user, setUser }), [user]);
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
}
// GOOD: use a selector library (use-context-selector, zustand)
import { useContextSelector } from 'use-context-selector';
const name = useContextSelector(UserContext, ctx => ctx.user.name);
// BAD: one giant context
const AppContext = createContext({ user, theme, settings, cart });
// Changing cart re-renders components that only use theme
// GOOD: split into separate contexts
const UserContext = createContext(null);
const ThemeContext = createContext('light');
const CartContext = createContext([]);
// GOOD: memoize context value
function Provider({ children }) {
const [user, setUser] = useState(null);
const value = useMemo(() => ({ user, setUser }), [user]);
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
}
// GOOD: use a selector library (use-context-selector, zustand)
import { useContextSelector } from 'use-context-selector';
const name = useContextSelector(UserContext, ctx => ctx.user.name);
Why
React context doesn't have fine-grained subscriptions. When the Provider value changes (by reference), React walks the component tree and re-renders every Consumer. If the value is a new object on each render ({...}), every consumer re-renders every time.
Gotchas
- value={{ a, b }} creates a new object every render — always memoize
- Context is not a state management replacement — it's for dependency injection
- Zustand or Jotai provide fine-grained subscriptions without extra context
- React.memo on consumers doesn't help — context bypasses memo
Code Snippets
Memoized context value
// Memoize context value
const value = useMemo(() => ({ user, login, logout }), [user]);
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>Context
When React context causes unnecessary re-renders in large applications
Revisions (0)
No revisions yet.