React NativeExamples · Props · Code

React Native Weather App

A weather app is the classic first real project: fetch data from an API, ask for location permission, and render it. Here’s a working version using Open-Meteo (free, no API key) and expo-location.

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}&current=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)

PropTypeDefaultDescription
temperature_2mnumberCurrent air temperature (°C by default).
weather_codenumberWMO code; map to an icon/label.
wind_speed_10mnumberAdd to the "current" query param to get it.
temperature_unitstring'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 fetch in try/catch and show an error state, or the app hangs on the spinner forever.
  • expo-location needs config in app.json (iOS location usage string) or the build is rejected.
  • Don’t fetch on every render. Put the call in useEffect with 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.

Related components

Skip the boilerplate

Describe your screen in ShipNative and it wires up the component for you — in a real, exportable React Native app.

Generate it with AI →