Day 6: Fetching Data from APIs


In this tutorial, you’ll learn how to fetch data from an external API and display it in your app. APIs are crucial for building dynamic apps that interact with servers, databases, or other external services. Today, we will fetch real-time data and display it using the skills we’ve learned in previous lessons.


What You Will Learn Today:

  1. Making HTTP requests using the fetch API
  2. Displaying fetched data in a list using FlatList
  3. Handling loading states and error messages
  4. Understanding how to interact with real-world APIs

Step 1: Fetching Data from an API

React Native uses the standard JavaScript fetch API to make HTTP requests. Let’s start by fetching data from a public API.

We’ll use a sample API, JSONPlaceholder, which provides dummy data for testing.

Modify HomeScreen.js to fetch and display a list of posts from this API.

import React, { useState, useEffect } from 'react';
import { View, Text, FlatList, ActivityIndicator, StyleSheet } from 'react-native';

export default function HomeScreen() {
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState([]);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then((response) => response.json())
      .then((json) => setData(json))
      .catch((error) => setError(error))
      .finally(() => setLoading(false));
  }, []);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Fetched Data from API</Text>

      {loading ? (
        <ActivityIndicator size="large" color="#6200EE" />
      ) : error ? (
        <Text style={styles.error}>Error fetching data: {error.message}</Text>
      ) : (
        <FlatList
          data={data}
          keyExtractor={(item) => item.id.toString()}
          renderItem={({ item }) => (
            <View style={styles.listItem}>
              <Text style={styles.itemTitle}>{item.title}</Text>
              <Text>{item.body}</Text>
            </View>
          )}
        />
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
    backgroundColor: '#f5f5f5',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
  listItem: {
    padding: 10,
    backgroundColor: '#f9c2ff',
    marginVertical: 8,
    borderRadius: 10,
    width: '100%',
  },
  itemTitle: {
    fontSize: 16,
    fontWeight: 'bold',
  },
  error: {
    color: 'red',
    fontSize: 16,
  },
});

Explanation:

  • useEffect: We use the useEffect hook to run the fetch request when the component mounts (only once).
  • fetch: This method sends a GET request to the API and retrieves a list of posts.
  • ActivityIndicator: Displays a loading spinner while the data is being fetched.
  • FlatList: Displays the fetched posts in a scrollable list.
See also  Day 4: Authentication Using JWT (JSON Web Tokens)

Step 2: Displaying Data from the API

In the above code, once the data is fetched from the API, it is displayed in a FlatList. The list items contain the title and body of each post.

Key Features:

  • Loading State: We use the loading state to show a spinner while the data is being fetched.
  • Error Handling: If an error occurs during the fetch, we display an error message.
  • Rendering List Items: Each post is rendered in a list item with its title and body.

Step 3: Displaying a Loader and Handling Errors

It’s important to handle the state of the app while the data is being fetched. We do this by displaying a loading spinner and handling any potential errors.

  1. Loading State: While the data is being fetched, the ActivityIndicator component shows a spinner to indicate that something is happening.
  2. Error Handling: If there’s an error during the fetch, an error message is displayed.

In the code above, this is handled by:

{loading ? (
  <ActivityIndicator size="large" color="#6200EE" />
) : error ? (
  <Text style={styles.error}>Error fetching data: {error.message}</Text>
) : (
  <FlatList
    data={data}
    keyExtractor={(item) => item.id.toString()}
    renderItem={({ item }) => (
      <View style={styles.listItem}>
        <Text style={styles.itemTitle}>{item.title}</Text>
        <Text>{item.body}</Text>
      </View>
    )}
  />
)}

Explanation:

  • ActivityIndicator: Shows a loading spinner when loading is true.
  • Error Message: If error is set, an error message is shown to the user.

Step 4: Fetching Data on Another Screen

Let’s extend this by fetching data on the DetailsScreen. We’ll modify the DetailsScreen.js to fetch details of a single post.

Modify DetailsScreen.js as follows:

import React, { useState, useEffect } from 'react';
import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';

export default function DetailsScreen({ route }) {
  const { postId } = route.params;
  const [loading, setLoading] = useState(true);
  const [post, setPost] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`)
      .then((response) => response.json())
      .then((json) => setPost(json))
      .catch((error) => setError(error))
      .finally(() => setLoading(false));
  }, [postId]);

  return (
    <View style={styles.container}>
      {loading ? (
        <ActivityIndicator size="large" color="#6200EE" />
      ) : error ? (
        <Text style={styles.error}>Error fetching post: {error.message}</Text>
      ) : (
        <View style={styles.postContainer}>
          <Text style={styles.postTitle}>{post.title}</Text>
          <Text>{post.body}</Text>
        </View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
    backgroundColor: '#f5f5f5',
  },
  postContainer: {
    backgroundColor: '#fff',
    padding: 20,
    borderRadius: 10,
    width: '100%',
  },
  postTitle: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  error: {
    color: 'red',
    fontSize: 16,
  },
});

Explanation:

  • Fetching Single Post: This time, we’re fetching a single post by its ID using the API endpoint https://jsonplaceholder.typicode.com/posts/{id}.
  • useEffect Hook: The useEffect hook fetches the post data when the postId changes.
  • The fetched post is displayed on the DetailsScreen.
See also  Advanced Form Handling with Alpine.js and Laravel

To test this, modify HomeScreen.js to pass a postId when navigating to the DetailsScreen:

<Button
  title="Go to Details"
  onPress={() => navigation.navigate('Details', { postId: item.id })}
/>

Now, clicking a button on the Home screen will navigate to the Details screen and display details about a specific post.


Step 5: Recap and Summary

Today, you learned how to fetch data from an external API and display it in your app. Here’s a quick summary of what you’ve done:

  • Made an API request using the fetch method.
  • Displayed a list of data from the API using FlatList.
  • Implemented a loading state with an activity indicator.
  • Handled errors by displaying error messages to the user.
  • Fetched data dynamically on multiple screens.

Your app is now connected to an external data source, making it dynamic and interactive. You can now retrieve and display real-time data from an API!


Next Up: Day 7 – Managing Global State with Redux

In Day 7, we’ll introduce Redux for managing global state across different components in your app. You’ll learn how to set up Redux, create actions and reducers, and share state between different screens.

Stay tuned for more advanced state management tomorrow!


Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.