useContext Hook
Passing props through many nested levels (prop drilling) gets tedious. The Context API lets you share values like themes, auth state, or language preferences to any component in the tree without passing props manually at every level.
Creating and Providing Context
// 1. Create context (with optional default value)
const ThemeContext = React.createContext("light");
// 2. Provide a value at any level of the tree
function App() {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Layout />
</ThemeContext.Provider>
);
}
Consuming Context
// 3. Consume in any child โ no matter how deeply nested
import { useContext } from "react";
function ThemeToggle() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button onClick={() => setTheme(t => t === "light" ? "dark" : "light")}>
Current theme: {theme} โ Toggle
</button>
);
}
// ThemeToggle can be deeply nested inside Layout โ Sidebar โ Footer
// and it will still receive theme without props
Real-World Example โ Auth Context
// contexts/AuthContext.jsx
const AuthContext = React.createContext(null);
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = async (email, password) => {
const res = await fetch("/api/login", {
method: "POST",
body: JSON.stringify({ email, password }),
});
const data = await res.json();
setUser(data.user);
};
const logout = () => setUser(null);
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
}
// Custom hook โ cleaner than calling useContext directly
export function useAuth() {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error("useAuth must be used inside <AuthProvider>");
return ctx;
}
// Usage anywhere in the app
function NavBar() {
const { user, logout } = useAuth();
return user
? <button onClick={logout}>Sign out ({user.name})</button>
: <a href="/login">Sign in</a>;
}
WarningContext re-renders all consumers when its value changes. Avoid putting fast-changing data (like mouse position) in context. Split large contexts into focused ones: AuthContext, ThemeContext, CartContext.