When to Use Context
Context is ideal for sharing data that is needed by many components at different nesting levels:- Current authenticated user
- Theme preferences (dark/light mode)
- Language/locale settings
- UI state (modals, notifications)
Creating Context
UsecreateContext to create a new context object. It accepts a default value that’s used when a component doesn’t have a matching Provider above it.
Implementation Details
ThecreateContext function is implemented in src/create-context.js. It returns a special component that acts as both Provider and Consumer:
src/create-context.js:6-60
Provider Component
Every Context object comes with a Provider component that allows consuming components to subscribe to context changes.import { createContext } from 'preact';
import { useState } from 'preact/hooks';
const ThemeContext = createContext('light');
function App() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={theme}>
<Toolbar />
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle Theme
</button>
</ThemeContext.Provider>
);
}
const ThemeContext = createContext('light');
const UserContext = createContext(null);
function App() {
return (
<ThemeContext.Provider value="dark">
<UserContext.Provider value={{ name: 'Alice', role: 'admin' }}>
<Dashboard />
</UserContext.Provider>
</ThemeContext.Provider>
);
}
import { createContext } from 'preact';
import { useState } from 'preact/hooks';
const AuthContext = createContext(null);
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const login = (username, password) => {
// Login logic
setUser({ username });
};
const logout = () => {
setUser(null);
};
const value = {
user,
login,
logout
};
return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
);
}
Consuming Context
There are two ways to consume context in Preact:- useContext Hook (Recommended)
- Consumer Component
The Reference:
useContext hook is the recommended way to consume context in function components:How useContext Works
TheuseContext hook is implemented in hooks/src/index.js. It reads the context value from the current component’s context and subscribes to updates:hooks/src/index.js:367-385Practical Examples
Best Practices
// Good: Separate contexts
const ThemeContext = createContext();
const AuthContext = createContext();
const NotificationContext = createContext();
// Less ideal: One giant context
const AppContext = createContext({
theme: 'light',
user: null,
notifications: []
});
import { createContext } from 'preact';
import { useContext } from 'preact/hooks';
const UserContext = createContext(null);
export function useUser() {
const context = useContext(UserContext);
if (!context) {
throw new Error('useUser must be used within UserProvider');
}
return context;
}
import { useMemo, useState } from 'preact/hooks';
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
// Good: Memoize the value object
const value = useMemo(
() => ({
user,
login: () => { /* ... */ },
logout: () => { /* ... */ }
}),
[user]
);
return (
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
);
}
Performance Considerations
Context updates cause all consuming components to re-render. Here are strategies to optimize:- Split Contexts
- Memoize Context Values
- Component Splitting
Split frequently changing values into separate contexts:Now components that only need theme won’t re-render when user changes.
Next Steps
Hooks
Learn more about hooks including useContext
Refs
Work with DOM references and forward refs