Context
Context ofrece una forma de compartir estado entre componentes sin prop drilling.
Crear un context
import { createContext } from '@emberkit/core';
interface ThemeContext {
theme: 'light' | 'dark';
toggle: () => void;
}
const ThemeContext = createContext<ThemeContext>({
theme: 'light',
toggle: () => {},
});
Proveer valores
Usa el Provider para hacer un valor disponible a los componentes descendientes:
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>
);
}
Consumir valores
Usa useContext para leer el context en cualquier componente descendiente:
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>
);
}
Usar el método use
Cada context devuelto por createContext también tiene un atajo use:
const ThemeContext = createContext<{ theme: string }>({ theme: 'light' });
function Header() {
const { theme } = ThemeContext.use();
return <span>Theme: {theme}</span>;
}
Valores por defecto
Si no hay un Provider encima del consumidor, se usa el valor por defecto:
const UserContext = createContext<{ name: string }>({ name: 'Guest' });
// En un componente sin Provider encima:
function Greeting() {
const user = useContext(UserContext);
return <span>Hello, {user.name}</span>; // "Hello, Guest"
}
Ejemplo completo
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>
);
}
Próximos pasos
- Signals — Primitivas de estado reactivo
- Componentes — Patrones de componentes
- Routing — Context a nivel de ruta