Mamun Labs Learn
JourneyGlossary
esc
  • Try “map”, “flexbox” or “state”.
Log in
Start learning
Phase 6 · 10 / 10Calling an API
Phase 6React Native with Expo
10 topics · 6–8 wks
  1. 1Your first Expo app
  2. 2View, Text and Image
  3. 3Pressable and TextInput
  4. 4Styling and flexbox on mobile
  5. 5Lists with FlatList
  6. 6Safe areas and the keyboard
  7. 7Screens and navigation
  8. 8Tabs
  9. 9Saving data on the phone
  10. 10Calling an API
JourneyPhase 6Calling an API
01 / 09Overview

Calling an API

You'll learn to load data from the internet into a phone screen, with a loading spinner and an error message.

Why it mattersReal apps show data from a server, and a phone is often on slow or no internet, so every screen needs all three states.
about 90 min·needs: Fetching data in React, Saving data on the phone
02 / 09

Watch & read

Start with the required ones. The others are there when you need them.

Docs
Networkingreactnative.dev · official docs · 10 min · English
MMamun's noteRead "Using Fetch" and run the example. It loads a list of movies, shows an ActivityIndicator while loading and the list in a FlatList when done. Skip the WebSocket part at the end.
Video
React Native for Dummies 2026: full beginner crash courseYouTube · Code with Beto · 9 min · English
MMamun's noteWatch 24:00–32:24. Beto looks at a free Pokémon API in the browser first, then fetches it in a useEffect with try and catch, and saves the result with useState. He shows it in a ScrollView; you would use FlatList. Stop before the TypeScript type at 34:23.
ToolOptional
DummyJSON quotesdummyjson.com · 5 min · English
MMamun's noteThe free endpoint the drill uses. No key or sign-up. Open the random quote address in your browser first, so you know the shape of the data before you write any code.
03 / 09

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, show ActivityIndicator, 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.

Words to recognise
ActivityIndicatorendpointhttps
04 / 09

Code tour

Click a line number with a ring to read the note for that line.

src/components/QuoteCard.jsx5 notes
1import { useEffect, useState } from "react";
2import { ActivityIndicator, Text } from "react-native";
3export default function QuoteCard() {
4 const [quote, setQuote] = useState(null);
const [loading, setLoading] = useState(true);
Mentor note · line 5
Three pieces of state for three situations. It starts as loading, because the request starts right away.
6 const [error, setError] = useState(null);
7 useEffect(() => {
8 fetch("https://dummyjson.com/quotes/random")
.then((res) => res.json()).then((data) => setQuote(data))
.catch(() => setError("Could not load a quote. Check your internet."))
.finally(() => setLoading(false));
12 }, []);
if (loading) return <ActivityIndicator size="large" />;
14 if (error) return <Text>{error}</Text>;
15 return <Text>"{quote.quote}" by {quote.author}</Text>;
16}
05 / 09

Practice

Short drills. Take your time and read the code before you answer.

DrillPredict1 / 2
1export default function QuoteCard() {
2 const [quote, setQuote] = useState(null);
3
4 useEffect(() => {
5 fetch("https://dummyjson.com/quotes/random")
6 .then((res) => res.json())
7 .then((data) => setQuote(data));
8 }, []);
9
10 return <Text>{quote ? quote.quote : "Loading…"}</Text>;
11}
12// The internet is fast and working.
What appears first?
DrillA quote for today2 / 2
This card loads a motivation quote for your Today tab. Add an error message for when the request fails, and a button that loads a new quote.
1import { useEffect, useState } from "react";
2import { ActivityIndicator, StyleSheet, Text, View } from "react-native";
3
4export 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.

Working whenA "New quote" button under the card loads a different quote, with the spinner showing while it loads.If you change the address to https://dummyjson.invalid/quotes/random (a site that does not exist), the screen shows a friendly error message instead of a blank screen. Add an error state and a .catch.The error message has a "Try again" button that calls loadQuote.
Check each goal yourself, then mark it.
06 / 09

Quick check

3 questions. Each one explains itself after you answer.

  1. 1 / 3Where does the fetch for a screen's data go?
  2. 2 / 3Why call setLoading(false) in finally instead of only after the data arrives?
  3. 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?
07 / 09

Explain it back

Only you can see this. Log in to keep it.0 words
08 / 09

How confident are you with Calling an API?

09 / 09

Done

You can now
Read a screen that calls fetch and say what it shows while loading, after success and after an error.
Next: The game loop Back to Phase 6
On this page
  1. 01Calling an API
  2. 02Watch & read
  3. 03Explanation
  4. 04Code tour
  5. 05Practice
  6. 06Quick check
  7. 07Explain it back
  8. 08Confidence
  9. 09Done
Up next · 02 / 09Watch & read
Mamun Labs LearnFound a mistake on this page? Tell Mamun.
Mamun Labs Learn
JourneyGlossary
esc
  • Try “map”, “flexbox” or “state”.
Log in
Start learning
Log in to save your progress. Everything here works without an account.Log in to save progressLog in
Phase 6React Native with Expo
10 topics · 6–8 wks
  1. 1Your first Expo app
  2. 2View, Text and Image
  3. 3Pressable and TextInput
  4. 4Styling and flexbox on mobile
  5. 5Lists with FlatList
  6. 6Safe areas and the keyboard
  7. 7Screens and navigation
  8. 8Tabs
  9. 9Saving data on the phone
  10. 10Calling an API
JourneyPhase 6Calling an API
01 / 09Overview

Calling an API

You'll learn to load data from the internet into a phone screen, with a loading spinner and an error message.

Why it mattersReal apps show data from a server, and a phone is often on slow or no internet, so every screen needs all three states.
about 90 min·needs: Fetching data in React, Saving data on the phone
02 / 09

Watch & read

Start with the required ones. The others are there when you need them.

Docs
Networkingreactnative.dev · official docs · 10 min · English
MMamun's noteRead "Using Fetch" and run the example. It loads a list of movies, shows an ActivityIndicator while loading and the list in a FlatList when done. Skip the WebSocket part at the end.
Video
React Native for Dummies 2026: full beginner crash courseYouTube · Code with Beto · 9 min · English
MMamun's noteWatch 24:00–32:24. Beto looks at a free Pokémon API in the browser first, then fetches it in a useEffect with try and catch, and saves the result with useState. He shows it in a ScrollView; you would use FlatList. Stop before the TypeScript type at 34:23.
ToolOptional
DummyJSON quotesdummyjson.com · 5 min · English
MMamun's noteThe free endpoint the drill uses. No key or sign-up. Open the random quote address in your browser first, so you know the shape of the data before you write any code.
03 / 09

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, show ActivityIndicator, 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.

Words to recognise
ActivityIndicatorendpointhttps
04 / 09

Code tour

Click a line number with a ring to read the note for that line.

src/components/QuoteCard.jsx5 notes
1import { useEffect, useState } from "react";
2import { ActivityIndicator, Text } from "react-native";
3export default function QuoteCard() {
4 const [quote, setQuote] = useState(null);
const [loading, setLoading] = useState(true);
Mentor note · line 5
Three pieces of state for three situations. It starts as loading, because the request starts right away.
6 const [error, setError] = useState(null);
7 useEffect(() => {
8 fetch("https://dummyjson.com/quotes/random")
.then((res) => res.json()).then((data) => setQuote(data))
.catch(() => setError("Could not load a quote. Check your internet."))
.finally(() => setLoading(false));
12 }, []);
if (loading) return <ActivityIndicator size="large" />;
14 if (error) return <Text>{error}</Text>;
15 return <Text>"{quote.quote}" by {quote.author}</Text>;
16}
05 / 09

Practice

Short drills. Take your time and read the code before you answer.

DrillPredict1 / 2
1export default function QuoteCard() {
2 const [quote, setQuote] = useState(null);
3
4 useEffect(() => {
5 fetch("https://dummyjson.com/quotes/random")
6 .then((res) => res.json())
7 .then((data) => setQuote(data));
8 }, []);
9
10 return <Text>{quote ? quote.quote : "Loading…"}</Text>;
11}
12// The internet is fast and working.
What appears first?
DrillA quote for today2 / 2
This card loads a motivation quote for your Today tab. Add an error message for when the request fails, and a button that loads a new quote.
1import { useEffect, useState } from "react";
2import { ActivityIndicator, StyleSheet, Text, View } from "react-native";
3
4export 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.

Working whenA "New quote" button under the card loads a different quote, with the spinner showing while it loads.If you change the address to https://dummyjson.invalid/quotes/random (a site that does not exist), the screen shows a friendly error message instead of a blank screen. Add an error state and a .catch.The error message has a "Try again" button that calls loadQuote.
Check each goal yourself, then mark it.
06 / 09

Quick check

3 questions. Each one explains itself after you answer.

  1. 1 / 3Where does the fetch for a screen's data go?
  2. 2 / 3Why call setLoading(false) in finally instead of only after the data arrives?
  3. 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?
07 / 09

Explain it back

Only you can see this. Log in to keep it.0 words
08 / 09

How confident are you with Calling an API?

09 / 09

Done

You can now
Read a screen that calls fetch and say what it shows while loading, after success and after an error.
Next: The game loop Back to Phase 6
On this page
  1. 01Calling an API
  2. 02Watch & read
  3. 03Explanation
  4. 04Code tour
  5. 05Practice
  6. 06Quick check
  7. 07Explain it back
  8. 08Confidence
  9. 09Done
Up next · 02 / 09Watch & read

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, show ActivityIndicator, 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.

Words to recognise
ActivityIndicatorendpointhttps

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, show ActivityIndicator, 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.

Words to recognise
ActivityIndicatorendpointhttps