What you’ll build
A screen that reads the device’s location, fetches the current temperature from a free weather API, and displays it — handling the loading, error, and permission states you actually hit in a real app.
1. Fetch the weather
Open-Meteo needs no API key, which makes it perfect for a tutorial or MVP. Wrap the fetch and check res.ok:
import { useEffect, useState } from 'react';
// Open-Meteo is free and needs no API key.
async function getWeather(lat, lon) {
const url =
`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,weather_code`;
const res = await fetch(url);
if (!res.ok) throw new Error('Weather request failed');
const data = await res.json();
return data.current; // { temperature_2m, weather_code, ... }
}2. Get location and render
Request permission, read the coordinates, then fetch. Always render distinct loading, error, and success states:
import { useEffect, useState } from 'react';
import { ActivityIndicator, Text, View } from 'react-native';
import * as Location from 'expo-location'; // npx expo install expo-location
function WeatherScreen() {
const [weather, setWeather] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
(async () => {
try {
const { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') { setError('Location permission denied'); return; }
const { coords } = await Location.getCurrentPositionAsync({});
setWeather(await getWeather(coords.latitude, coords.longitude));
} catch (e) {
setError(e.message);
}
})();
}, []);
if (error) return <Text style={{ padding: 24 }}>{error}</Text>;
if (!weather) return <ActivityIndicator style={{ marginTop: 80 }} />;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ fontSize: 64, fontWeight: '200' }}>
{Math.round(weather.temperature_2m)}°
</Text>
<Text style={{ fontSize: 18, color: '#6b7280' }}>Current temperature</Text>
</View>
);
}API response fields (Open-Meteo)
| Prop | Type | Default | Description |
|---|---|---|---|
| temperature_2m | number | — | Current air temperature (°C by default). |
| weather_code | number | — | WMO code; map to an icon/label. |
| wind_speed_10m | number | — | Add to the "current" query param to get it. |
| temperature_unit | string | 'celsius' | Add &temperature_unit=fahrenheit for °F. |
Gotchas
- Location permission can be denied. Always handle
status !== 'granted'— don’t assume you have coordinates. - Network calls fail. Wrap
fetchin try/catch and show an error state, or the app hangs on the spinner forever. expo-locationneeds config inapp.json(iOS location usage string) or the build is rejected.- Don’t fetch on every render. Put the call in
useEffectwith an empty dependency array (or a pull-to-refresh handler).
FAQ
What’s a free weather API for React Native? Open-Meteo — no key, generous limits. OpenWeatherMap is the other common one (needs a free key).
How do I get the user’s location? expo-location: request permission, then getCurrentPositionAsync.