Share state "globally" across your component tree without passing props manually at every level. Great for themes, users, or language settings.
First, create the context object. This will be the source of truth.
import { createContext } from 'react';
// Create context with a default value
export const ThemeContext = createContext('light');Wrap your component tree in the Provider. The `value` prop is what will be shared.
import { useState } from 'react';
import { ThemeContext } from './ThemeContext';
function App() {
const [theme, setTheme] = useState('dark');
return (
// 🌍 Every component inside here can access 'theme'
<ThemeContext.Provider value={theme}>
<Header />
<MainContent />
</ThemeContext.Provider>
);
}Any child component can simply ask for the data using `useContext`.
import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';
function MyComponent() {
// ⚡️ Grab the value directly! No props needed.
const theme = useContext(ThemeContext);
return <div className={theme}>I am styled!</div>;
}Context becomes powerful when you share both the state and the functions to update it.
// 1. Context Object
const AuthContext = createContext(null);
// 2. Provider Component
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = (name) => setUser({ name });
const logout = () => setUser(null);
// 3. Pass object with data AND functions
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
}function LoginButton() {
// 4. Consume and use functions!
const { user, login, logout } = useContext(AuthContext);
if (user) {
return <button onClick={logout}>Log Out</button>;
}
return <button onClick={() => login('Alice')}>Log In</button>;
}When the Provider's value changes, every component that calls `useContext` will re-render. Be careful not to put too much unrelated data into a single Context context context.