Calling an API
You'll learn to load data from the internet into a phone screen, with a loading spinner and an error message.
Watch & read
Start with the required ones. The others are there when you need them.
Explanation
You want the Today tab of your habit tracker to show a new motivation quote each day, from a free quote
service on the internet. Good news: this is the same fetch you used in React on the web. React Native
has fetch built in.
Think of ordering a rickshaw ride on an app. First you see "finding a driver", then either the driver's name or "no driver found". A screen that loads data also has three states: loading, done and error. Your job is to show something for each.
const res = await fetch("https://dummyjson.com/quotes/random");if (!res.ok) throw new Error("Server said " + res.status);const data = await res.json(); // { id: 556, quote: "...", author: "Mark Twain" }
The web address you call is the endpoint. Put the fetch in a useEffect with [] so it runs once
when the screen opens, inside try, catch and finally:
- loading:
useState(true)at the start. While it is true, showActivityIndicator, React Native's built-in spinner:<ActivityIndicator size="large" />. - done: save the data with a setter, then show it.
- error: in
catch, save a message and show it, with a "Try again" button that runs the same function.
Use https addresses. Phones block plain http by default in real builds, so an http endpoint that
works in your browser can fail on the phone.
People often forget the error state on a phone. On a laptop the Wi-Fi is usually on. On a phone, the
user walks into a lift and the request fails. If loading is only set back to false after a success,
the spinner spins forever. Set it in finally, so it stops either way.
When you read a screen that loads data, find the three pieces of state, then check that every path through
try, catch and finally leaves the screen showing something useful.
Code tour
Click a line number with a ring to read the note for that line.
Practice
Short drills. Take your time and read the code before you answer.
1export default function QuoteCard() {2 const [quote, setQuote] = useState(null);34 useEffect(() => {5 fetch("https://dummyjson.com/quotes/random")6 .then((res) => res.json())7 .then((data) => setQuote(data));8 }, []);910 return <Text>{quote ? quote.quote : "Loading…"}</Text>;11}12// The internet is fast and working.
1import { useEffect, useState } from "react";2import { ActivityIndicator, StyleSheet, Text, View } from "react-native";34export default function App() {5 const [quote, setQuote] = useState(null);6 const [loading, setLoading] = useState(true);
Runs in the browser. Choose “My Device” in Snack to try it on your phone with Expo Go.
Quick check
3 questions. Each one explains itself after you answer.
- 1 / 3Where does the
fetchfor a screen's data go? - 2 / 3Why call
setLoading(false)infinallyinstead of only after the data arrives? - 3 / 3Your app calls
http://myschool.example/api(no s). It works in the laptop browser but fails on the phone. What is the likely reason?
Explain it back
How confident are you with Calling an API?
Done
fetch and say what it shows while loading, after success and after an error.