Context
Context permet de partager l'état entre composants sans prop drilling.
Créer un context
import { createContext } from '@emberkit/core';
interface ThemeContext {
theme: 'light' | 'dark';
toggle: () => void;
}
const ThemeContext = createContext<ThemeContext>({
theme: 'light',
toggle: () => {},
});
Fournir des valeurs
Utilisez le Provider pour rendre une valeur disponible aux composants descendants :
import { createContext, createSignal } from '@emberkit/core';
const ThemeContext = createContext<{ theme: string; toggle: () => void }>();
function App() {
const [theme, setTheme] = createSignal('light');
const toggle = () => setTheme(t => t === 'light' ? 'dark' : 'light');
return (
<ThemeContext.Provider value={{ theme: theme(), toggle }}>
<Header />
<main>...</main>
</ThemeContext.Provider>
);
}
Consommer des valeurs
Utilisez useContext pour lire le context dans n'importe quel composant descendant :
import { useContext } from '@emberkit/core';
function Header() {
const ctx = useContext(ThemeContext);
return (
<header>
<span>Current theme: {ctx.theme}</span>
<button onClick={ctx.toggle}>Toggle</button>
</header>
);
}
Utiliser la méthode use
Chaque context retourné par createContext a aussi un raccourci use :
const ThemeContext = createContext<{ theme: string }>({ theme: 'light' });
function Header() {
const { theme } = ThemeContext.use();
return <span>Theme: {theme}</span>;
}
Valeurs par défaut
S'il n'y a pas de Provider au-dessus d'un consommateur, la valeur par défaut est utilisée :
const UserContext = createContext<{ name: string }>({ name: 'Guest' });
// Dans un composant sans Provider au-dessus :
function Greeting() {
const user = useContext(UserContext);
return <span>Hello, {user.name}</span>; // "Hello, Guest"
}
Exemple complet
import { createContext, useContext, createSignal } from '@emberkit/core';
interface AuthContext {
user: string | null;
login: (name: string) => void;
logout: () => void;
}
const AuthContext = createContext<AuthContext>({
user: null,
login: () => {},
logout: () => {},
});
function AuthProvider({ children }: { children: unknown }) {
const [user, setUser] = createSignal<string | null>(null);
return (
<AuthContext.Provider value={{
user: user(),
login: (name) => setUser(name),
logout: () => setUser(null),
}}>
{children}
</AuthContext.Provider>
);
}
function Navbar() {
const { user, logout } = useContext(AuthContext);
return (
<nav>
{user ? (
<>
<span>Welcome, {user}</span>
<button onClick={logout}>Logout</button>
</>
) : (
<span>Please log in</span>
)}
</nav>
);
}
Prochaines étapes
- Signals — Primitives d'état réactif
- Composants — Patterns de composants
- Routing — Context au niveau route