Module 6: API Integration & Data Fetching

Learn to integrate APIs and handle data fetching in React Native applications.

Back to Course|4.5 hours|Intermediate

API Integration & Data Fetching

Learn to integrate APIs and handle data fetching in React Native applications.

Progress: 0/4 topics completed0%

Select Topics Overview

Fetch API & Axios

Learn to use Fetch API and Axios for making HTTP requests in React Native applications, understanding their differences and use cases

Content by: Pratik Keshvala

React Native Developer

Connect

Fetch API

Fetch API is a modern, promise-based API for making HTTP requests. It's built into React Native and provides a clean, simple interface for network requests.

Axios Library

Axios is a popular HTTP client library that provides more features than Fetch, including automatic JSON parsing, request/response interceptors, and better error handling.

Installing Axios

Install Axios: `npm install axios`. Axios works out of the box with React Native and provides better TypeScript support and more features than Fetch.

API Integration Example

Code Example
import React, { useState, useEffect } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, FlatList, ActivityIndicator, Alert } from 'react-native';
import axios from 'axios';

// API Configuration
const API_BASE_URL = 'https://jsonplaceholder.typicode.com';

// API Service
const apiService = {
  // Fetch API example
  fetchUsers: async () => {
    try {
      const response = await fetch(`${API_BASE_URL}/users`);
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      return await response.json();
    } catch (error) {
      console.error('Fetch error:', error);
      throw error;
    }
  },

  // Axios example
  fetchPosts: async () => {
    try {
      const response = await axios.get(`${API_BASE_URL}/posts`);
      return response.data;
    } catch (error) {
      console.error('Axios error:', error);
      throw error;
    }
  },

  // POST request with Axios
  createPost: async (postData) => {
    try {
      const response = await axios.post(`${API_BASE_URL}/posts`, postData, {
        headers: {
          'Content-Type': 'application/json',
        },
      });
      return response.data;
    } catch (error) {
      console.error('Create post error:', error);
      throw error;
    }
  },

  // PUT request with Axios
  updatePost: async (id, postData) => {
    try {
      const response = await axios.put(`${API_BASE_URL}/posts/${id}`, postData);
      return response.data;
    } catch (error) {
      console.error('Update post error:', error);
      throw error;
    }
  },

  // DELETE request with Axios
  deletePost: async (id) => {
    try {
      const response = await axios.delete(`${API_BASE_URL}/posts/${id}`);
      return response.data;
    } catch (error) {
      console.error('Delete post error:', error);
      throw error;
    }
  },
};

// User Component
const UserList = () => {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const loadUsers = async () => {
    setLoading(true);
    setError(null);
    try {
      const userData = await apiService.fetchUsers();
      setUsers(userData);
    } catch (err) {
      setError(err.message);
      Alert.alert('Error', 'Failed to load users');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    loadUsers();
  }, []);

  const renderUser = ({ item }) => (
    <View style={styles.userItem}>
      <Text style={styles.userName}>{item.name}</Text>
      <Text style={styles.userEmail}>{item.email}</Text>
      <Text style={styles.userWebsite}>{item.website}</Text>
    </View>
  );

  return (
    <View style={styles.section}>
      <Text style={styles.sectionTitle}>Users (Fetch API)</Text>
      
      {loading && <ActivityIndicator size="large" color="#2196F3" />}
      
      {error && (
        <View style={styles.errorContainer}>
          <Text style={styles.errorText}>{error}</Text>
          <TouchableOpacity style={styles.retryButton} onPress={loadUsers}>
            <Text style={styles.retryButtonText}>Retry</Text>
          </TouchableOpacity>
        </View>
      )}

      <FlatList
        data={users}
        keyExtractor={item => item.id.toString()}
        renderItem={renderUser}
        style={styles.list}
        refreshing={loading}
        onRefresh={loadUsers}
      />
    </View>
  );
};

// Posts Component
const PostList = () => {
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const loadPosts = async () => {
    setLoading(true);
    setError(null);
    try {
      const postData = await apiService.fetchPosts();
      setPosts(postData.slice(0, 10)); // Limit to first 10 posts
    } catch (err) {
      setError(err.message);
      Alert.alert('Error', 'Failed to load posts');
    } finally {
      setLoading(false);
    }
  };

  const createNewPost = async () => {
    const newPost = {
      title: 'New Post',
      body: 'This is a new post created from the app',
      userId: 1,
    };

    try {
      const createdPost = await apiService.createPost(newPost);
      setPosts(prev => [createdPost, ...prev]);
      Alert.alert('Success', 'Post created successfully!');
    } catch (err) {
      Alert.alert('Error', 'Failed to create post');
    }
  };

  const deletePost = async (id) => {
    try {
      await apiService.deletePost(id);
      setPosts(prev => prev.filter(post => post.id !== id));
      Alert.alert('Success', 'Post deleted successfully!');
    } catch (err) {
      Alert.alert('Error', 'Failed to delete post');
    }
  };

  useEffect(() => {
    loadPosts();
  }, []);

  const renderPost = ({ item }) => (
    <View style={styles.postItem}>
      <Text style={styles.postTitle}>{item.title}</Text>
      <Text style={styles.postBody}>{item.body}</Text>
      <View style={styles.postActions}>
        <TouchableOpacity 
          style={styles.actionButton} 
          onPress={() => deletePost(item.id)}
        >
          <Text style={styles.actionButtonText}>Delete</Text>
        </TouchableOpacity>
      </View>
    </View>
  );

  return (
    <View style={styles.section}>
      <Text style={styles.sectionTitle}>Posts (Axios)</Text>
      
      <TouchableOpacity style={styles.createButton} onPress={createNewPost}>
        <Text style={styles.createButtonText}>Create New Post</Text>
      </TouchableOpacity>

      {loading && <ActivityIndicator size="large" color="#2196F3" />}
      
      {error && (
        <View style={styles.errorContainer}>
          <Text style={styles.errorText}>{error}</Text>
          <TouchableOpacity style={styles.retryButton} onPress={loadPosts}>
            <Text style={styles.retryButtonText}>Retry</Text>
          </TouchableOpacity>
        </View>
      )}

      <FlatList
        data={posts}
        keyExtractor={item => item.id.toString()}
        renderItem={renderPost}
        style={styles.list}
        refreshing={loading}
        onRefresh={loadPosts}
      />
    </View>
  );
};

// Main App
const App = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>API Integration Example</Text>
      <UserList />
      <PostList />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#f5f5f5',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    textAlign: 'center',
    marginBottom: 30,
    color: '#333',
  },
  section: {
    marginBottom: 30,
    backgroundColor: 'white',
    padding: 20,
    borderRadius: 8,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  sectionTitle: {
    fontSize: 20,
    fontWeight: 'bold',
    marginBottom: 15,
    color: '#333',
  },
  list: {
    maxHeight: 200,
  },
  userItem: {
    padding: 15,
    borderBottomWidth: 1,
    borderBottomColor: '#e0e0e0',
  },
  userName: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#333',
    marginBottom: 5,
  },
  userEmail: {
    fontSize: 14,
    color: '#666',
    marginBottom: 2,
  },
  userWebsite: {
    fontSize: 12,
    color: '#999',
  },
  postItem: {
    padding: 15,
    borderBottomWidth: 1,
    borderBottomColor: '#e0e0e0',
  },
  postTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#333',
    marginBottom: 5,
  },
  postBody: {
    fontSize: 14,
    color: '#666',
    marginBottom: 10,
  },
  postActions: {
    flexDirection: 'row',
    justifyContent: 'flex-end',
  },
  actionButton: {
    backgroundColor: '#f44336',
    padding: 8,
    borderRadius: 5,
  },
  actionButtonText: {
    color: 'white',
    fontSize: 12,
    fontWeight: 'bold',
  },
  createButton: {
    backgroundColor: '#4CAF50',
    padding: 15,
    borderRadius: 8,
    alignItems: 'center',
    marginBottom: 15,
  },
  createButtonText: {
    color: 'white',
    fontSize: 16,
    fontWeight: 'bold',
  },
  errorContainer: {
    alignItems: 'center',
    padding: 20,
  },
  errorText: {
    color: '#f44336',
    fontSize: 14,
    textAlign: 'center',
    marginBottom: 10,
  },
  retryButton: {
    backgroundColor: '#2196F3',
    padding: 10,
    borderRadius: 5,
  },
  retryButtonText: {
    color: 'white',
    fontSize: 14,
    fontWeight: 'bold',
  },
});

export default App;
Swipe to see more code

šŸŽÆ Practice Exercise

Test your understanding of this topic:

Ready for the Next Module?

Continue your learning journey and master the next set of concepts.

Continue to Module 7