Topic 8 of 15 · React Native

Topic 8 : HTTP

Lesson TL;DRTopic 8: HTTP 📖 7 min read · 🎯 intermediate · 🧭 Prerequisites: basicsstylescomponentstextinputsbuttonsscrollviewactivityindicatorimagesmodals, basicspickerstatusbarasyncstorage Why this matters Up ...
7 min read·intermediate·http · axios · api · fetch

Topic 8: HTTP

📖 7 min read · 🎯 intermediate · 🧭 Prerequisites: basics-stylescomponents-text-inputs-buttons-scrollview-activity-indicator-images-modals, basics-picker-status-bar-async-storage

Why this matters

Up until now, every app we've built has been a closed box — all the data lives inside the app itself. But think about every real app you use: WhatsApp fetches your messages, Swiggy pulls the latest menu, Cricbuzz loads live scores. None of that data lives on your phone. It comes from a server, over the internet, every time you open the app. That's HTTP — and today we're going to wire our React Native app to do exactly that, using Axios to send GET requests that fetch data and POST requests that send data out.

What You'll Learn

  • Install and configure Axios, the promise-based HTTP client for JavaScript
  • Create a service file that centralises API requests using async/await
  • Fetch data from a REST API and render it with FlatList
  • Send data to a REST API using axios.post and display the server response

The Analogy

Think of Axios as a courier service operating out of your app. When you want information from a remote server, you hand Axios a addressed envelope (the URL and any parameters), and it rides out, knocks on the server's door, waits for a reply, and brings the package back to your component. If the server is unavailable or the address is wrong, the courier returns an error note instead of an empty-handed shrug — which is why Axios wraps every trip in a promise you can await and a catch block you can rely on.

Chapter 1: Setting Up Axios

Axios is a promise-based HTTP client for JavaScript. It simplifies sending asynchronous HTTP requests to REST endpoints and performing CRUD operations compared to the raw fetch API — it automatically parses JSON responses, handles request/response interceptors, and produces descriptive error objects.

Install Axios by running:

npm install axios

Once installed, import it anywhere in your project:

import axios from 'axios';

That single import gives you axios.get, axios.post, axios.put, axios.patch, and axios.delete — one method per HTTP verb.

Chapter 2: Fetching Data from an API

The class's first goal: pull posts from a public REST API and render them in a scrollable list.

Step 1 — Create a Service File

Centralising API calls in a dedicated service file keeps your components clean and makes it trivial to swap endpoints later.

api.js:

import axios from 'axios';

const API_URL = 'https://jsonplaceholder.typicode.com';

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

response.data is where Axios places the parsed JSON body — you never need to call .json() manually the way you would with fetch.

Step 2 — Create a Component to Display Data

PostsComponent.js:

import React, { useEffect, useState } from 'react';
import { View, Text, FlatList, StyleSheet } from 'react-native';
import { fetchPosts } from './api';

const PostsComponent = () => {
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const getPosts = async () => {
      try {
        const postsData = await fetchPosts();
        setPosts(postsData);
        setLoading(false);
      } catch (error) {
        setError(error);
        setLoading(false);
      }
    };

    getPosts();
  }, []);

  if (loading) {
    return <Text>Loading...</Text>;
  }

  if (error) {
    return <Text>Error: {error.message}</Text>;
  }

  return (
    <FlatList
      data={posts}
      keyExtractor={(item) => item.id.toString()}
      renderItem={({ item }) => (
        <View style={styles.post}>
          <Text style={styles.title}>{item.title}</Text>
          <Text>{item.body}</Text>
        </View>
      )}
    />
  );
};

const styles = StyleSheet.create({
  post: {
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#ccc',
  },
  title: {
    fontSize: 18,
    fontWeight: 'bold',
  },
});

export default PostsComponent;

Key patterns here:

  • Three state slices — posts, loading, error — cover every possible UI state.
  • The useEffect with an empty dependency array [] fires once on mount, triggering the fetch.
  • keyExtractor converts item.id (a number) to a string because React Native's FlatList requires string keys.

Step 3 — Integrate the Component in App

App.js:

import React from 'react';
import { StyleSheet, ScrollView, View } from 'react-native';
import PostsComponent from './PostsComponent';

export default function App() {
  return (
    <ScrollView contentContainerStyle={styles.container}>
      <PostsComponent />
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  container: {
    flexGrow: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 16,
  },
});
sequenceDiagram
    participant App
    participant PostsComponent
    participant api.js
    participant JSONPlaceholder

    App->>PostsComponent: renders
    PostsComponent->>api.js: fetchPosts()
    api.js->>JSONPlaceholder: GET /posts
    JSONPlaceholder-->>api.js: 200 OK, JSON array
    api.js-->>PostsComponent: response.data
    PostsComponent->>PostsComponent: setPosts(), setLoading(false)
    PostsComponent-->>App: renders FlatList

Chapter 3: Sending Data to an API

Reading data is only half the story. The class also needs to create new posts — which means sending a POST request with a JSON body.

Step 1 — Update the Service File

Add a createPost export alongside fetchPosts.

api.js (full file):

import axios from 'axios';

const API_URL = 'https://jsonplaceholder.typicode.com';

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

export const createPost = async (postData) => {
  try {
    const response = await axios.post(`${API_URL}/posts`, postData);
    return response.data;
  } catch (error) {
    console.error('Error creating post:', error);
    throw error;
  }
};

axios.post takes the URL as the first argument and the request body as the second. Axios automatically serialises the object to JSON and sets the Content-Type: application/json header.

Step 2 — Create a Component to Send Data

CreatePostComponent.js:

import React, { useState } from 'react';
import { View, TextInput, Button, Text, StyleSheet } from 'react-native';
import { createPost } from './api';

const CreatePostComponent = () => {
  const [title, setTitle] = useState('');
  const [body, setBody] = useState('');
  const [response, setResponse] = useState(null);

  const handleCreatePost = async () => {
    const postData = { title, body };
    try {
      const postResponse = await createPost(postData);
      setResponse(postResponse);
    } catch (error) {
      console.error('Error creating post:', error);
    }
  };

  return (
    <View style={styles.container}>
      <TextInput
        style={styles.input}
        placeholder="Title"
        value={title}
        onChangeText={setTitle}
      />
      <TextInput
        style={styles.input}
        placeholder="Body"
        value={body}
        onChangeText={setBody}
      />
      <Button title="Create Post" onPress={handleCreatePost} />
      {response && (
        <View style={styles.response}>
          <Text>Post Created:</Text>
          <Text>ID: {response.id}</Text>
          <Text>Title: {response.title}</Text>
          <Text>Body: {response.body}</Text>
        </View>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 16,
    backgroundColor: '#fff',
    borderRadius: 8,
    marginVertical: 16,
  },
  input: {
    height: 40,
    borderColor: 'gray',
    borderWidth: 1,
    marginBottom: 12,
    paddingHorizontal: 8,
  },
  response: {
    marginTop: 16,
  },
});

export default CreatePostComponent;

The response state is null until a successful POST returns — the conditional {response && ...} block then renders the server-echoed fields (id, title, body). JSONPlaceholder always returns a fake id: 101 for new posts, confirming the round-trip worked.

Step 3 — Integrate Both Components in App

App.js (final version):

import React from 'react';
import { StyleSheet, ScrollView, View } from 'react-native';
import PostsComponent from './PostsComponent';
import CreatePostComponent from './CreatePostComponent';

export default function App() {
  return (
    <ScrollView contentContainerStyle={styles.container}>
      <CreatePostComponent />
      <PostsComponent />
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  container: {
    flexGrow: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 16,
  },
});

CreatePostComponent sits above PostsComponent so the form appears at the top, and the fetched list scrolls below it.

🧪 Try It Yourself

Task: Add a deletePost function to api.js that calls axios.delete, then build a DeletePostComponent with a numeric TextInput for the post ID and a "Delete Post" button. On success, display the message "Post [ID] deleted successfully."

Success criterion: Pressing the button with a valid post ID (e.g., 1) should log no errors to the console and render the success message beneath the button. JSONPlaceholder returns an empty {} body with status 200 for DELETE — treat a non-null response as success.

Starter snippet:

// api.js — add below createPost
export const deletePost = async (postId) => {
  try {
    const response = await axios.delete(`${API_URL}/posts/${postId}`);
    return response.data;
  } catch (error) {
    console.error('Error deleting post:', error);
    throw error;
  }
};

🔍 Checkpoint Quiz

Q1. Why does axios.get not require a .json() call on the response, unlike the native fetch API?

A) Axios only works with JSON APIs and throws otherwise B) Axios automatically parses the JSON response body and places it on response.data C) React Native patches fetch to auto-parse JSON D) The jsonplaceholder.typicode.com API sends pre-parsed objects

Q2. Given this snippet, what is logged to the console if the network request fails?

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

A) Nothing — errors are silently swallowed B) 'Error fetching posts:' followed by the error object, then the error is re-thrown to the caller C) 'Error fetching posts:' followed by the error object; execution continues normally D) The component automatically shows a fallback UI

Q3. What is the purpose of the empty dependency array [] passed to useEffect in PostsComponent?

A) It disables the effect entirely B) It causes the effect to re-run every time any state changes C) It causes the effect to run once after the initial render and never again D) It passes an empty posts array as initial data

Q4. You want to update a post's title without replacing the whole document. Which Axios method and endpoint pattern should you use?

A) axios.post('/posts/1', { title: 'New title' }) B) axios.put('/posts/1', { title: 'New title' }) — replaces the full resource C) axios.patch('/posts/1', { title: 'New title' }) — partial update, only sends changed fields D) axios.get('/posts/1/update?title=New+title')

A1. B — Axios parses JSON automatically and exposes the result on response.data, removing the need for a second .json() await step.

A2. B — The catch block logs the error with console.error, then throw error re-throws it so the calling component's own catch block can also handle it (e.g., set error state).

A3. C — An empty [] dependency array tells React to run the effect only after the first render (equivalent to componentDidMount). Without it, the effect would re-run after every state change, causing an infinite fetch loop.

A4. C — axios.patch is the correct choice for partial updates. axios.put replaces the entire resource, which would wipe fields you didn't include in the request body.

🪞 Recap

  • Install Axios with npm install axios; import it with import axios from 'axios'.
  • Centralise API calls in a service file (e.g., api.js) using async/await and try/catch for clean error handling.
  • axios.get(url) fetches data; the parsed JSON body lives on response.data.
  • axios.post(url, body) sends data; Axios serialises the object to JSON and sets the correct Content-Type header automatically.
  • Manage three state slices — data, loading, error — in components that fetch, so every UI state is handled.

📚 Further Reading

Like this topic? It’s one of 15 in React Native.

Block your seat for ₹2,500 and join the next cohort.