Tipar contextos y custom hooks
Cree un contexto tipado con valores predeterminados y escriba custom hooks con tipos de retorno explícitos.
Tipar contextos y custom hooks es una lección gratuita de React Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de React Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de React Academy incluye 4 lecciones en total.
Context tipado con createContext
Proporcione el tipo del contexto y un valor predeterminado a createContext. Utilice null como valor predeterminado cuando el contexto deba utilizarse dentro de un proveedor y gestione este caso con una guardia.
interface AuthContextType {
user: User | null;
login: (credentials: Credentials) => Promise<void>;
logout: () => void;
}
const AuthContext = createContext<AuthContextType | null>(null);Patrón de hook con guardia
Cree un hook personalizado que lea el contexto y lance una excepción si se utiliza fuera de su proveedor. Así se eliminan las comprobaciones de null en cada punto de llamada.
export function useAuth(): AuthContextType {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
return ctx;
}Tipar el proveedor
El componente proveedor envuelve a los hijos y proporciona el valor del contexto. Tipe explícitamente el objeto de valor para que TypeScript verifique que coincide con el tipo del contexto.
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const login = async (creds: Credentials) => {
const u = await apiLogin(creds);
setUser(u);
};
const logout = () => setUser(null);
return (
<AuthContext.Provider value={{ user, login, logout }}>
{children}
</AuthContext.Provider>
);
}Contexto con valor predeterminado
Cuando existe un valor predeterminado adecuado, como un tema, páselo directamente a createContext para que el contexto nunca sea null y no se necesite un hook de guardia.
interface ThemeContextType { theme: 'light' | 'dark'; toggle: () => void; }
const ThemeContext = createContext<ThemeContextType>({
theme: 'light',
toggle: () => {},
});
export const useTheme = () => useContext(ThemeContext);Tipar los valores de retorno de hooks personalizados
Anote explícitamente el tipo de retorno de los hooks personalizados o deje que TypeScript lo infiera. Los tipos explícitos sirven como documentación y evitan cambios accidentales en la forma.
interface UseCounterReturn {
count: number;
increment: () => void;
decrement: () => void;
reset: () => void;
}
function useCounter(initial = 0): UseCounterReturn {
const [count, setCount] = useState(initial);
return {
count,
increment: () => setCount(c => c + 1),
decrement: () => setCount(c => c - 1),
reset: () => setCount(initial),
};
}Tipos de retorno de tuplas
Los hooks que devuelven un par, como useState, utilizan tuplas. Típelas con as const o con un tipo de tupla explícito para que la desestructuración se infiera correctamente.
function useToggle(initial = false): [boolean, () => void] {
const [value, setValue] = useState(initial);
const toggle = useCallback(() => setValue(v => !v), []);
return [value, toggle];
}
// Destructuring correctly infers types:
const [isOpen, toggleOpen] = useToggle();Hooks personalizados genéricos
Los hooks personalizados también pueden ser genéricos. Un hook genérico useLocalStorage almacena cualquier tipo serializable con seguridad de tipos completa.
function useLocalStorage<T>(key: string, initialValue: T): [T, (val: T) => void] {
const [stored, setStored] = useState<T>(() => {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch { return initialValue; }
});
const setValue = (val: T) => {
setStored(val);
localStorage.setItem(key, JSON.stringify(val));
};
return [stored, setValue];
}Tipar useReducer
Defina los tipos de las acciones como uniones discriminadas y la forma del estado como una interfaz. TypeScript impondrá tipos de acción válidos en el reducer.
interface State { count: number; status: 'idle' | 'loading'; }
type Action =
| { type: 'INCREMENT' }
| { type: 'SET_STATUS'; payload: State['status'] };
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'INCREMENT': return { ...state, count: state.count + 1 };
case 'SET_STATUS': return { ...state, status: action.payload };
}
}
const [state, dispatch] = useReducer(reducer, { count: 0, status: 'idle' });Tipar useCallback y useMemo
TypeScript infiere los tipos de useCallback y useMemo a partir de la función de fábrica. Anote los tipos explícitamente solo cuando la inferencia falle.
const handleChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
onChange(e.target.value);
},
[onChange]
);
const sorted = useMemo(
() => [...items].sort((a, b) => a.name.localeCompare(b.name)),
[items]
); // inferred as typeof itemsPatrón de selector de contexto con tipos
Un hook selector tipado recibe una función selectora y devuelve únicamente la parte necesaria, conservando toda la inferencia de tipos.
function useAuthSelector<T>(selector: (ctx: AuthContextType) => T): T {
const ctx = useAuth();
return selector(ctx);
}
// Usage — TypeScript infers User | null:
const user = useAuthSelector(ctx => ctx.user);Evitar any en los hooks
No utilice nunca any en hooks personalizados. Utilice genéricos, unknown con guardias de tipo o interfaces específicas para mantener intacta la cadena de tipos.
// Bad:
function useFetch(url: string): { data: any; loading: boolean } { ... }
// Good:
function useFetch<T>(url: string): { data: T | null; loading: boolean } {
const [data, setData] = useState<T | null>(null);
// ...
return { data, loading };
}Comprobación rápida
¿Cuál es el propósito del patrón de hook con guardia al tipar el contexto de React?
Resumen
Tipa el contexto con una interfaz explícita y un hook que gestione null mediante una guardia. Anote los tipos de retorno de los hooks personalizados con interfaces o tipos de tupla, utilice genéricos para crear hooks reutilizables y tipa useReducer con acciones de unión discriminada para detectar despachos no válidos en tiempo de compilación.
Preguntas frecuentes
¿La lección «Tipar contextos y custom hooks» es gratis?
Sí — el texto completo de «Tipar contextos y custom hooks» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de React Academy, actualiza a CoddyKit PRO. El curso de React Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Tipar contextos y custom hooks»?
Cree un contexto tipado con valores predeterminados y escriba custom hooks con tipos de retorno explícitos. Practicas React Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar React Academy?
No se requiere experiencia previa. React Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.
¿Cuánto tiempo toma la lección «Tipar contextos y custom hooks»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de React Academy?
Sí. Cada lección de React Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Tipar props y tipos de retorno de componentes
- Tipar eventos y refs en TypeScript
- Componentes genéricos y tipos utilitarios
- Tipar contextos y custom hooks