useContext returns the current context value for the given context. The value is determined by the nearest <Context.Provider> above the calling component in the tree.
Signature
function useContext<T>(context: PreactContext<T>): T
Parameters
The context object created by createContext. The hook reads the current value from the nearest provider for this context.
Returns
Returns the current context value of type T. The value is determined by the value prop of the nearest <Context.Provider> above the calling component. If there is no provider, the default value passed to createContext is returned.
Basic Usage
import { createContext } from 'preact';
import { useContext } from 'preact/hooks';
const ThemeContext = createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button className={`theme-${theme}`}>
I am styled by theme context
</button>
);
}
function App() {
return (
<ThemeContext.Provider value="dark">
<ThemedButton />
</ThemeContext.Provider>
);
}
Multiple Contexts
const ThemeContext = createContext('light');
const UserContext = createContext(null);
const LanguageContext = createContext('en');
function UserProfile() {
const theme = useContext(ThemeContext);
const user = useContext(UserContext);
const language = useContext(LanguageContext);
return (
<div className={`theme-${theme}`}>
<h1>{language === 'en' ? 'Welcome' : 'Bienvenido'}</h1>
<p>{user?.name}</p>
</div>
);
}
function App() {
const [user, setUser] = useState({ name: 'John' });
return (
<ThemeContext.Provider value="dark">
<UserContext.Provider value={user}>
<LanguageContext.Provider value="en">
<UserProfile />
</LanguageContext.Provider>
</UserContext.Provider>
</ThemeContext.Provider>
);
}
With TypeScript
import { createContext } from 'preact';
import { useContext } from 'preact/hooks';
interface Theme {
primary: string;
secondary: string;
background: string;
}
const ThemeContext = createContext<Theme>({
primary: '#007bff',
secondary: '#6c757d',
background: '#ffffff'
});
function ThemedComponent() {
const theme = useContext(ThemeContext);
return (
<div style={{ backgroundColor: theme.background }}>
<button style={{ color: theme.primary }}>Primary</button>
<button style={{ color: theme.secondary }}>Secondary</button>
</div>
);
}
Updating Context Value
import { createContext } from 'preact';
import { useContext, useState } from 'preact/hooks';
const ThemeContext = createContext({
theme: 'light',
toggleTheme: () => {}
});
function ThemeToggle() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<button onClick={toggleTheme}>
Current theme: {theme}
</button>
);
}
function App() {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
<ThemeToggle />
</ThemeContext.Provider>
);
}
Authentication Context
const AuthContext = createContext({
user: null,
login: () => {},
logout: () => {}
});
function useAuth() {
return useContext(AuthContext);
}
function LoginButton() {
const { user, login, logout } = useAuth();
if (user) {
return (
<div>
<span>Welcome, {user.name}</span>
<button onClick={logout}>Logout</button>
</div>
);
}
return <button onClick={login}>Login</button>;
}
function App() {
const [user, setUser] = useState(null);
const login = async () => {
const userData = await fetchUser();
setUser(userData);
};
const logout = () => {
setUser(null);
};
return (
<AuthContext.Provider value={{ user, login, logout }}>
<LoginButton />
</AuthContext.Provider>
);
}
Complex State in Context
const AppContext = createContext();
function reducer(state, action) {
switch (action.type) {
case 'set-user':
return { ...state, user: action.payload };
case 'set-theme':
return { ...state, theme: action.payload };
case 'add-notification':
return {
...state,
notifications: [...state.notifications, action.payload]
};
default:
return state;
}
}
function App() {
const [state, dispatch] = useReducer(reducer, {
user: null,
theme: 'light',
notifications: []
});
return (
<AppContext.Provider value={{ state, dispatch }}>
{/* App components */}
</AppContext.Provider>
);
}
function SomeComponent() {
const { state, dispatch } = useContext(AppContext);
const notify = (message) => {
dispatch({ type: 'add-notification', payload: message });
};
return <div>{state.theme}</div>;
}
When the value prop of the nearest <Context.Provider> updates, all components that call useContext with that context will re-render, even if their parent would normally prevent re-rendering.
The context value is always taken from the nearest provider above the component. Context does not “tunnel” through intermediate components.
If there is no provider for a context above the component, useContext returns the default value that was passed to createContext.