React Native: custom hook para a API OpenWeather
Isole num custom hook a lógica de acesso à API de clima do OpenWeather, com estados de carregamento e erro, e use-o num app React Native com TypeScript.
1. Visão geral
Neste material, vamos estudar sobre a criação de hooks próprios, visando a implementação de regras de negócio que podem se repetir em diferentes partes da aplicação. A motivação é a mesma que utilizamos quando criamos funções: promover reusabilidade, manutenabilidade e flexibilidade. Quando utilizamos Hooks, estamos optando por seguir tais princípios aderindo a convenções do React.
A aplicação que criaremos isola a lógica de acesso a uma API de condições climáticas. Ela se parece com o seguinte.

A aplicação de condições climáticas.
O que você vai aprender
- Definir tipos TypeScript de acordo com a resposta de uma API
- Escrever um custom hook que usa
useState,useEffectefetch - Controlar os estados de carregamento e de erro de uma requisição
- Usar o hook num componente com
TextInput,ButtoneActivityIndicator
O que você vai precisar
- Node.js e VS Code instalados
- Uma chave de API do OpenWeather (https://openweathermap.org/)
- Ter feito o codelab
rn-custom-hooksajuda
2. Criando a aplicação
Comece criando a aplicação com
Terminal
npx create-expo-app -t expo-template-blank-typescript custom-hooks-openweather
Uma pasta chamada custom-hooks-openweather terá sido criada para você. Use
Terminal
code custom-hooks-openweather
para abrir uma instância do VS Code vinculada a ela. No VS Code, clique Terminal >> New Terminal, obtendo um terminal interno. Como vamos testar a aplicação no navegador num primeiro momento, instale as dependências para tal com
Terminal do VS Code
npx expo install react-native-web react-dom @expo/metro-runtime
Coloque a aplicação para funcionar com
Terminal do VS Code
npm start
No terminal, aperte w para vê-la funcionar no navegador. Se necessário, abra o navegador manualmente e visite
http://localhost:8081/
Abra o arquivo App.tsx e ajuste seu conteúdo como a seguir.
App.tsx
import { StyleSheet, Text, View } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<Text>Nosso primeiro Custom hook</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
3. O hook useWeather
Crie a seguinte estrutura para isolar os hooks da aplicação.

A estrutura src/hooks/useWeather.ts.
Tipos
No arquivo useWeather.ts, criamos o hook. Começamos com a definição de tipos em TypeScript.
src/hooks/useWeather.ts
import { useState, useEffect } from 'react';
const API_KEY = '';
const BASE_URL = 'https://api.openweathermap.org/data/2.5/weather';
//define o tipo recebido da api
//estrutura criada de acordo com aquilo que o serviço devolve
interface WeatherInfo {
description: string;
}
interface WeatherResponse {
name: string;
main: {
temp: number;
};
weather: WeatherInfo[];
}
//definição daquilo que nosso hook devolve
interface UseWeatherReturn {
dados: WeatherResponse | null;
carregando: boolean;
erro: string | null;
buscarClima: () => Promise<void>;
}
O hook
A seguir, a definição do hook.
src/hooks/useWeather.ts
...
//definição daquilo que nosso hook devolve
interface UseWeatherReturn {
dados: WeatherResponse | null;
carregando: boolean;
erro: string | null;
buscarClima: () => Promise<void>;
}
...
export function useWeather(cidade: string = 'São Paulo'): UseWeatherReturn {
const [dados, setDados] = useState<WeatherResponse | null>(null);
const [carregando, setCarregando] = useState(true);
const [erro, setErro] = useState<string | null>(null);
const buscarClima = async () => {
try {
setCarregando(true);
setErro(null);
const resposta = await fetch(
`${BASE_URL}?q=${cidade}&appid=${API_KEY}&units=metric&lang=pt_br`
);
if (!resposta.ok) {
throw new Error('Erro ao buscar dados do clima');
}
const json: WeatherResponse = await resposta.json();
setDados(json);
} catch (e: any) {
setErro(e.message);
} finally {
setCarregando(false);
}
};
useEffect(() => {
buscarClima();
}, [cidade]);
return { dados, carregando, erro, buscarClima };
}
4. Usando o hook no App
Visite o arquivo App.tsx e apague todo o seu conteúdo. Começamos com os imports e definição de variáveis por meio de hooks. É nesse momento que utilizamos aquele que criamos.
App.tsx
import { useState } from 'react';
import { Text, View, StyleSheet, TextInput, Button, ActivityIndicator } from 'react-native';
import { useWeather } from './src/hooks/useWeather';
export default function App() {
const [cidade, setCidade] = useState<string>('São Paulo');
const { dados, carregando, erro, buscarClima } = useWeather(cidade);
return (
<View> Começando... </View>
);
}
Agora, a expressão JSX do componente, além da sua definição de estilos.
App.tsx
export default function App() {
const [cidade, setCidade] = useState<string>('São Paulo');
const { dados, carregando, erro, buscarClima } = useWeather(cidade);
return (
<View style={styles.container}>
<Text style={styles.titulo}>🌦 Previsão do Tempo</Text>
<TextInput
style={styles.input}
placeholder="Digite a cidade"
value={cidade}
onChangeText={setCidade}
/>
<Button title="Buscar" onPress={buscarClima} />
{carregando && <ActivityIndicator size="large" color="#0000ff" />}
{erro && <Text style={styles.erro}>{erro}</Text>}
{dados && !carregando && (
<View style={styles.resultado}>
<Text style={styles.cidade}>{dados.name}</Text>
<Text style={styles.temperatura}>{Math.round(dados.main.temp)}°C</Text>
<Text style={styles.descricao}>{dados.weather[0].description}</Text>
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f0f0f0',
padding: 20,
},
titulo: {
fontSize: 28,
fontWeight: 'bold',
marginBottom: 20,
},
input: {
borderWidth: 1,
borderColor: '#ccc',
padding: 10,
borderRadius: 8,
marginBottom: 10,
width: '100%',
backgroundColor: '#fff',
},
erro: {
color: 'red',
marginTop: 10,
},
resultado: {
marginTop: 20,
alignItems: 'center',
},
cidade: {
fontSize: 24,
fontWeight: 'bold',
},
temperatura: {
fontSize: 48,
fontWeight: 'bold',
marginVertical: 10,
},
descricao: {
fontSize: 20,
fontStyle: 'italic',
},
});
5. Exercícios
Adapte a aplicação vista em aula de modo que os parâmetros (unidade de medida da temperatura, idioma etc.) sejam especificados no momento em que o hook é usado.
A aplicação que escrevemos utiliza o serviço de condições climáticas atuais. Visite o link a seguir e estude sobre o serviço de previsão do tempo de 3 em 3 horas por 5 dias.
https://openweathermap.org/forecast5
Faça uma nova aplicação que utiliza este serviço e exibe uma lista de previsões. Para cada previsão, inclua nome da cidade, temperaturas máxima e mínima, descrição e um ícone (cujo nome é provido pelo próprio serviço que estamos utilizando).
Referências
- React Native. Learn once, write anywhere. 2025. Disponível em https://reactnative.dev/. Acesso em 2025.