Building Your Learning Module...
Getting things ready for you!
Find videos you like?
Save to resource drawer for future reference!
When context value changes, ALL components that use that context will re-render, even if they only use a small part of the value!
Watch render counts increase when context changes!
const CounterContext = React.createContext();
function CounterProvider({ children }) {
const [count, setCount] = React.useState(0);
const [name, setName] = React.useState('John');
// ❌ BAD: New object every render causes all consumers to re-render
const value = { count, name, setCount, setName };
return (
<CounterContext.Provider value={value}>
{children}
</CounterContext.Provider>
);
}
// Component that only uses 'count'
function CountDisplay() {
const { count } = React.useContext(CounterContext);
const [renderCount, setRenderCount] = React.useState(0);
React.useEffect(() => {
setRenderCount(prev => prev + 1);
});
return (
<div className="component count-display">
<h3>Count Display</h3>
<p>Uses: <strong>count</strong> only</p>
<div className="value">Count: {count}</div>
<div className="render-badge">Renders: {renderCount}</div>
</div>
);
}
// Component that only uses 'name'
function NameDisplay() {
const { name } = React.useContext(CounterContext);
const [renderCount, setRenderCount] = React.useState(0);
React.useEffect(() => {
setRenderCount(prev => prev + 1);
});
return (
<div className="component name-display">
<h3>Name Display</h3>
<p>Uses: <strong>name</strong> only</p>
<div className="value">Name: {name}</div>
<div className="render-badge">Renders: {renderCount}</div>
</div>
);
}
// Controls
function Controls() {
const { count, name, setCount, setName } = React.useContext(CounterContext);
const [renderCount, setRenderCount] = React.useState(0);
React.useEffect(() => {
setRenderCount(prev => prev + 1);
});
return (
<div className="controls">
<div className="control-group">
<button onClick={() => setCount(count + 1)}>
Increment Count
</button>
<p className="hint">⚠️ Will re-render BOTH components</p>
</div>
<div className="control-group">
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Change name"
/>
<p className="hint">⚠️ Will re-render BOTH components</p>
</div>
<div className="render-badge">Control Renders: {renderCount}</div>
</div>
);
}
function App() {
return (
<CounterProvider>
<div className="demo-app">
<div className="header">
<h2>⚠️ Context Re-render Problem</h2>
<p>All consumers re-render when ANY context value changes!</p>
</div>
<div className="components-grid">
<CountDisplay />
<NameDisplay />
</div>
<Controls />
<div className="info">
<p><strong>Problem:</strong> Changing count re-renders NameDisplay (doesn't use count)</p>
<p><strong>Problem:</strong> Changing name re-renders CountDisplay (doesn't use name)</p>
<p><strong>Solution:</strong> Split into separate contexts or use useMemo!</p>
</div>
</div>
</CounterProvider>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);Loading preview...
Create separate contexts for different data that changes independently
const CountContext = createContext();
const NameContext = createContext();Use useMemo to prevent creating new object references
const value = useMemo(() => ({
count, name, setCount, setName
}), [count, name]);Wrap expensive components with React.memo to skip re-renders
const ExpensiveComponent = React.memo(
function Component() { /* ... */ }
);Context change triggers ALL consuming components
Separate contexts for independent data
Use useMemo to prevent unnecessary updates
Wrap expensive components to prevent re-renders