Tipando contextos e hooks personalizados
Crie contextos tipados com valores padrão e escreva hooks personalizados com tipos de retorno explícitos.
Tipando contextos e hooks personalizados é uma aula grátis de React Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de React Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de React Academy inclui 4 aulas no total.
Contexto tipado com createContext
Passe o tipo do contexto e um valor padrão para createContext. Use null como padrão quando o contexto precisar ser usado dentro de um provedor e trate esse caso com uma verificação.
interface AuthContextType {
user: User | null;
login: (credentials: Credentials) => Promise<void>;
logout: () => void;
}
const AuthContext = createContext<AuthContextType | null>(null);Padrão de gancho de proteção
Crie um gancho personalizado que leia o contexto e lance um erro se for usado fora do provedor. Isso elimina verificações de nulo em cada ponto de chamada.
export function useAuth(): AuthContextType {
const ctx = useContext(AuthContext);
if (!ctx) throw new Error('useAuth must be used within AuthProvider');
return ctx;
}Definindo o tipo do provedor
O componente provedor envolve os elementos filhos e fornece o valor do contexto. Defina explicitamente o tipo do objeto de valor para que o TypeScript verifique se ele corresponde ao tipo do 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 com valor padrão
Quando existir um padrão adequado, como um tema, passe-o diretamente para createContext para que o contexto nunca seja nulo e nenhum gancho de proteção seja necessário.
interface ThemeContextType { theme: 'light' | 'dark'; toggle: () => void; }
const ThemeContext = createContext<ThemeContextType>({
theme: 'light',
toggle: () => {},
});
export const useTheme = () => useContext(ThemeContext);Definindo os valores de retorno de ganchos personalizados
Anote explicitamente o tipo de retorno dos ganchos personalizados ou deixe o TypeScript inferi-lo. Tipos explícitos servem como documentação e impedem alterações acidentais na estrutura.
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 tupla
Ganchos que retornam um par, como useState, usam tuplas. Defina seus tipos com as const ou com um tipo de tupla explícito para que a desestruturação seja inferida corretamente.
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();Ganchos personalizados genéricos
Ganchos personalizados também podem ser genéricos. Um gancho genérico useLocalStorage armazena qualquer tipo serializável com segurança completa de tipos.
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];
}Definindo o tipo de useReducer
Defina os tipos das ações como uniões discriminadas e a estrutura do estado como uma interface. O TypeScript garantirá tipos de ação válidos no redutor.
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' });Definindo o tipo de useCallback e useMemo
O TypeScript infere os tipos de useCallback e useMemo a partir da função de criação. Faça uma anotação explícita apenas quando a inferência falhar.
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 itemsPadrão de seletor de contexto com tipos
Um gancho seletor tipado recebe uma função seletora e retorna apenas a parte necessária, preservando a inferência completa 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);Evitando any em ganchos
Nunca use any em ganchos personalizados. Use genéricos, unknown com verificações de tipo ou interfaces específicas para manter a cadeia de tipos intacta.
// 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 };
}Verificação rápida
Qual é a finalidade do padrão de gancho de proteção ao definir o tipo de um contexto do React?
Recapitulação
Defina o tipo do contexto com uma interface explícita e um gancho que proteja contra valores nulos. Anote os tipos de retorno de ganchos personalizados com interfaces ou tipos de tupla, use genéricos para ganchos reutilizáveis e defina o tipo de useReducer com ações de união discriminada para detectar despachos inválidos durante a compilação.
Perguntas Frequentes
A aula “Tipando contextos e hooks personalizados” é grátis?
Sim — o texto completo de “Tipando contextos e hooks personalizados” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de React Academy, atualize para CoddyKit PRO. O curso de React Academy inclui 4 aulas no total.
O que vou aprender em “Tipando contextos e hooks personalizados”?
Crie contextos tipados com valores padrão e escreva hooks personalizados com tipos de retorno explícitos. Você pratica React Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar React Academy?
Nenhuma experiência prévia é necessária. React Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Tipando contextos e hooks personalizados”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de React Academy?
Sim. Cada aula de React Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Tipando propriedades e tipos de retorno de componentes
- Tipando eventos e referências no TypeScript
- Componentes genéricos e tipos utilitários
- Tipando contextos e hooks personalizados