Questions
An expensive component is re-rendering unnecessarily. How would you fix this state management issue?
A junior developer built a new feature using React Context to manage the application’s global state. The state object contains everything: the current user’s info, and the UI theme (light/dark mode).
They’ve noticed a performance problem. The UserWelcome component, which is expensive to render, re-renders every single time the theme is changed. This is making the UI feel sluggish.
You’ve been given the code that demonstrates this issue.
- Explain why the
UserWelcomecomponent re-renders every time the “Toggle Theme” button is clicked. - Describe two different strategies to fix this performance issue so that
UserWelcomeonly re-renders when theuserdata it cares about actually changes.
import React, { useState, useContext, createContext } from 'react';
// The monolithic context holding all global state
const AppContext = createContext();
// A component that is "expensive" to render
function UserWelcome() {
const { user } = useContext(AppContext);
console.log('Re-rendering UserWelcome (expensive)...');
return <h1>Welcome, {user.name}!</h1>;
}
// A component to change the theme
function ThemeToggler() {
const { theme, setTheme } = useContext(AppContext);
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle Theme
</button>
);
}
// The main App provider
export default function App() {
const [user, setUser] = useState({ name: 'Alice' });
const [theme, setTheme] = useState('light');
const contextValue = { user, setUser, theme, setTheme };
return (
<AppContext.Provider value={contextValue}>
<div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff', padding: '20px' }}>
<ThemeToggler />
<hr />
<UserWelcome />
</div>
</AppContext.Provider>
);
} How Different Experience Levels Approach This
import React, { useState, useContext, createContext } from 'react'; // The monolithic context holding all global state const AppContext = createContext(); // A component that is "expensive" to render function UserWelcome() { const { user } = useContext(AppContext); console.log('Re-rendering UserWelcome (expensive)...'); return <h1>Welcome, {user.name}!</h1>; } // A component to change the theme function ThemeToggler() { const { theme, setTheme } = useContext(AppContext); return ( <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}> Toggle Theme </button> ); } // The main App provider export default function App() { const [user, setUser] = useState({ name: 'Alice' }); const [theme, setTheme] = useState('light'); const contextValue = { user, setUser, theme, setTheme }; return ( <AppContext.Provider value={contextValue}> <div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff', padding: '20px' }}> <ThemeToggler /> <hr /> <UserWelcome /> </div> </AppContext.Provider> ); }
// Solution 1: Split the Contexts (Best Practice) // Create two separate contexts const ThemeContext = createContext(); const UserContext = createContext(); function UserWelcome() { // Subscribe ONLY to the UserContext const { user } = useContext(UserContext); console.log('Re-rendering UserWelcome (expensive)...'); return <h1>Welcome, {user.name}!</h1>; } function ThemeToggler() { // Subscribe ONLY to the ThemeContext const { theme, setTheme } = useContext(ThemeContext); return ( <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}> Toggle Theme </button> ); } export default function App() { const [user, setUser] = useState({ name: 'Alice' }); const [theme, setTheme] = useState('light'); // Nest the providers return ( <ThemeContext.Provider value={{ theme, setTheme }}> <UserContext.Provider value={{ user, setUser }}> <div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff', padding: '20px' }}> <ThemeToggler /> <hr /> <UserWelcome /> </div> </UserContext.Provider> </ThemeContext.Provider> ); }
- Context over facts: Explains when and why, not just what
- Real examples: Provides specific use cases from production experience
- Trade-offs: Acknowledges pros, cons, and decision factors
Practice Question
What is the primary performance drawback of using a single, large React Context for unrelated pieces of state?