Trace theme from App → Layout → Sidebar → Panel → FilterSlider — 5 levels! Layout and Sidebar don't even use theme. They just pass it through.
const ThemeContext = createContext({
theme: 'dark', toggleTheme: () => {}
});
function ThemeProvider({ children }) {
const [theme, setTheme] =
useLocalStorage('theme', 'dark');
const toggleTheme = () =>
setTheme(t => t === 'dark' ? 'light' : 'dark');
return (
<ThemeContext.Provider
value={{ theme, toggleTheme }}>
<div className={
theme === 'dark' ? 'dark' : ''
}>
{children}
</div>
</ThemeContext.Provider>
);
}
// Any component, at any depth:
function FilterSlider() {
const { theme } = useContext(ThemeContext);
// Use theme directly — no props needed!
}
const EditorContext = createContext(null);
function EditorProvider({ children }) {
const [state, dispatch] = useReducer(
editorReducer, initialState
);
return (
<EditorContext.Provider
value={{ state, dispatch }}>
{children}
</EditorContext.Provider>
);
}
// Custom hook for easy access:
function useEditor() {
const context = useContext(EditorContext);
if (!context) throw new Error(
'useEditor must be used within EditorProvider'
);
return context;
}
const AuthContext = createContext(null);
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = async (credentials) => {
/* ... */
};
const logout = () => { setUser(null); };
return (
<AuthContext.Provider value={{
user, login, logout,
isAuthenticated: !!user
}}>
{children}
</AuthContext.Provider>
);
}
Wrap App with providers, remove 20+ prop-drilling instances. Verify: theme toggle works from any component, editor state accessible everywhere.
git switch -c refactor/PIXELCRAFT-039-context
git add src/
git commit -m "Add Theme/Editor/Auth contexts, remove prop drilling (PIXELCRAFT-039)"
git push origin refactor/PIXELCRAFT-039-context
# PR → Review → Merge → Close ticket ✅
Global state is a fundamental challenge in all complex systems.
React Context is the simplest version of this universal problem.