
ReactJS
Context is powerful, but every time the value changes, all components using that Context re-render. Understanding this helps you use Context wisely.
When Context value changes, every component that calls `useContext()` for that Context re-renders:
import { createContext, useContext, useState } from "react";
const CounterContext = createContext({ count: 0 });
function App() {
const [count, setCount] = useState(0);
// Value changes every render because of {...}
const value = { count };
return (
<CounterContext.Provider value={value}>
<Counter />
<ExpensiveComponent />
</CounterContext.Provider>
);
}
function Counter() {
const { count } = useContext(CounterContext);
return <h1>{count}</h1>; // Re-renders when count changes ✅
}
function ExpensiveComponent() {
// This component doesn't use Counter, but it re-renders anyway
return <VeryExpensiveCalculation />;
}Every time count changes, both Counter and ExpensiveComponent re-render, even though ExpensiveComponent doesn't need the count.
Context re-renders are problematic when:
1. The value changes frequently (like every keystroke)
2. Many components are listening to that Context
3. Components don't actually use the changed data
// ❌ Bad: Value is a new object every render
function BadApp() {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Content />
</ThemeContext.Provider>
);
// Every render creates new {theme, setTheme}, causing re-renders
}
// ✅ Good: Value only changes when state changes
function GoodApp() {
const [theme, setTheme] = useState("light");
const value = { theme, setTheme };
return (
<ThemeContext.Provider value={value}>
<Content />
</ThemeContext.Provider>
);
}Actually, the good example still has the same problem. Use `useMemo`:
import { useMemo } from "react";
function BestApp() {
const [theme, setTheme] = useState("light");
// Value only changes when theme changes
const value = useMemo(() => ({ theme, setTheme }), [theme]);
return (
<ThemeContext.Provider value={value}>
<Content />
</ThemeContext.Provider>
);
}<details>
<summary>📚 More Examples</summary>
// Example 1: Recognizing performance problems
function App() {
const [count, setCount] = useState(0);
const [name, setName] = useState("");
// ❌ Problem: Both count and name in same Context
// Changing count causes all useContext(DataContext) to re-render
// even if they only need name
return (
<DataContext.Provider value={{ count, name }}>
<NameDisplay /> {/* Re-renders on every count change */}
<CountDisplay /> {/* Re-renders on every count change */}
</DataContext.Provider>
);
}
// Example 2: Solution - split into separate contexts
function BetterApp() {
const [count, setCount] = useState(0);
const [name, setName] = useState("");
// ✅ Separate contexts allow independent re-renders
return (
<CountContext.Provider value={count}>
<NameContext.Provider value={name}>
<NameDisplay /> {/* Only re-renders on name change */}
<CountDisplay /> {/* Only re-renders on count change */}
</NameContext.Provider>
</CountContext.Provider>
);
}</details>
Context is great for:
Context is NOT great for:
// ✅ GOOD: Theme context - changes rarely
const ThemeContext = createContext("light");
function App() {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={theme}>
<Header />
<Content />
</ThemeContext.Provider>
);
}
// ❌ AVOID: Form input context - changes on every keystroke
const InputContext = createContext("");
function FormWithContextProblem() {
const [input, setInput] = useState("");
return (
<InputContext.Provider value={input}>
{/* This causes re-render on EVERY keystroke! */}
<Input />
<ExpensivePreview />
</InputContext.Provider>
);
}
// ✅ BETTER: Use useState directly in form component
function FormWithState() {
const [input, setInput] = useState("");
return (
<>
<input value={input} onChange={(e) => setInput(e.target.value)} />
<Preview value={input} />
</>
);
}| Data | Changes | Best Approach |
|---|---|---|
| Theme | Rarely | Context ✅ |
| Language | Rarely | Context ✅ |
| User info | Rarely | Context ✅ |
| Form input | Frequently | useState ✅ |
| Search query | Frequently | useState ✅ |
| Filters | Occasionally | useState + optional Context |
Ready to practice? Challenges | Next: Context Best Practices
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward