Skip to main content

Working with Network and API

1. Using Fetch API

Property Description Example
fetch() Method to make HTTP requests fetch('https://api.example.com/data')
method HTTP method (GET, POST, PUT, DELETE) { method: 'POST' }
headers Request headers to send { 'Content-Type': 'application/json' }
body Request body (for POST/PUT) JSON.stringify({ name: 'John' })

Example: Fetch GET request

const response = await fetch('https://api.example.com/users');
const data = await response.json();
console.log(data);

Example: Fetch POST request

const newUser = {
  name: 'Jane Doe',
  email: 'jane@example.com'
};

const response = await fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(newUser)
});

const result = await response.json();
console.log(result);
Note: In Expo, fetch is supported natively and works the same as in web browsers.

2. Making GET Requests

Example: Fetching Data from an API

import { useState, useEffect } from 'react';
import { fetch } from 'expo';

export default function UserProfile() {
  const [userData, setUserData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('https://api.example.com/user/123')
      .then(response => response.json())
      .then(data => {
        setUserData(data);
        setLoading(false);
      })
      .catch(error => {
        console.error('Error fetching user data:', error);
        setLoading(false);
      });
  }, []);

  if (loading) return <div>Loading...</div>;
  return <div>Hello, {userData.name}!</div>;
}
Property Description Default
url The URL to make the GET request to Required
headers Object containing headers to send with the request None
method The HTTP method (GET, POST, etc.) GET
Note: When using fetch in Expo, ensure that the API endpoint supports CORS if making requests to external domains.
Warning: Always handle potential errors in your GET requests to prevent unhandled promise rejections.

3. Making POST Requests

Property Description Example
url The endpoint to send the POST request to https://api.example.com/users
body Data to be sent in the request body { name: "John", age: 30 }
headers Optional headers to include in the request { "Content-Type": "application/json" }

Example: Sending a POST Request with Expo

import { fetch } from "expo";

const postData = {
  name: "John",
  age: 30
};

const response = await fetch("https://api.example.com/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify(postData)
});

console.log("Response:", response);

4. Sending Request Headers

Header Description Usage
Authorization Used for authentication with a server headers: { Authorization: 'Bearer token123' }
Content-Type Indicates the media type of the resource headers: { 'Content-Type': 'application/json' }
Accept Specifies the media types that are acceptable for the response headers: { Accept: 'application/json' }
User-Agent Identifies the client making the request headers: { 'User-Agent': 'Expo App v1.0' }

Example: Sending Custom Headers with Fetch

fetch('https://api.example.com/data', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer <token>',
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
})
.then(response => response.json())
.then(data => console.log(data));

5. Handling JSON Response

Method Description Return Type Example
fetch() Standard browser API to make HTTP requests Promise<Response> const response = await fetch('https://api.example.com/data');<br>const data = await response.json();
axios.get() Popular HTTP client for making GET requests Promise<AxiosResponse> const response = await axios.get('https://api.example.com/data');<br>const data = response.data;
expo-constants Access app constants including API endpoints Object import Constants from 'expo-constants';<br>const apiUrl = Constants.expoConfig.extra.apiUrl;
Note: When using fetch, always handle potential errors and check the response status before parsing JSON.
Warning: Never hardcode API keys or sensitive data in client-side code. Use environment variables or secure backend services.

6. Using Axios Library

Feature Description Notes
Installation npm install axios Available via npm or yarn
Basic GET Request
import axios from 'axios';

const response = await axios.get('https://api.example.com/data');
Promise-based HTTP client
Request Config
axios.get('/user', {
  params: { id: 123 },
  headers: { 'Authorization': 'Bearer token' }
});
Supports query params and headers

Example: Fetching Data with Axios

import axios from 'axios';

const fetchData = async () => {
  try {
    const response = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
    console.log(response.data);
  } catch (error) {
    console.error('Error fetching data:', error);
  }
};

fetchData();

Example: POST Request with Data

import axios from 'axios';

const postData = async () => {
  try {
    const response = await axios.post('https://jsonplaceholder.typicode.com/posts', {
      title: 'My New Post',
      body: 'This is the content of my post.',
      userId: 1
    });
    console.log('Created:', response.data);
  } catch (error) {
    console.error('Error posting data:', error);
  }
};

postData();
Note: Axios provides automatic JSON parsing and supports interceptors for request/response handling.
Warning: Ensure proper error handling when making network requests in mobile environments.

7. Implementing Interceptors

Interceptor Type Description Usage
Request Interceptor Modifies outgoing requests before they are sent axios.interceptors.request.use(config => { ... })
Response Interceptor Modifies incoming responses before they are handled axios.interceptors.response.use(response => { ... })

Example: Request Interceptor

import axios from 'axios';

const instance = axios.create({
  baseURL: 'https://api.example.com'
});

instance.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('authToken');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

Example: Response Interceptor

instance.interceptors.response.use(
  (response) => {
    console.log('Response received:', response);
    return response;
  },
  (error) => {
    if (error.response?.status === 401) {
      // Redirect to login or refresh token
      console.log('Unauthorized, redirecting...');
    }
    return Promise.reject(error);
  }
);
Note: Interceptors in Expo apps should be used carefully to avoid performance issues or infinite loops.

8. Handling Network Errors

Error Type Description Handling Strategy Example
TypeError Occurs when network request fails due to invalid URL or missing network Use try/catch and check for valid URL before making request
try {
  const response = await fetch('https://api.example.com/data');
  if (!response.ok) throw new Error('Network error');
} catch (error) {
  if (error instanceof TypeError) {
    console.error('Network unavailable:', error.message);
  }
}
NetworkError Indicates a failure in the network layer (e.g., timeout, DNS issues) Implement retry logic with exponential backoff Example: Retry Logic
async function fetchWithRetry(url, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url);
      if (!response.ok) throw new Error('Request failed');
      return response.json();
    } catch (error) {
      if (i === retries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, 2 ** i * 1000));
    }
  }
}
TimeoutError Request exceeds configured timeout threshold Set timeout limits and handle timeout gracefully
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000); // 5s timeout

fetch('https://api.example.com/data', {
  signal: controller.signal
}).catch(error => {
  if (error.name === 'AbortError') {
    console.error('Request timed out');
  }
});
Note: Always implement error boundaries in your app to gracefully handle network failures and provide user feedback.

Best Practices for Network Error Handling

  • Use try/catch blocks around network calls
  • Implement retry logic for transient errors
  • Set timeouts to prevent hanging requests
  • Provide user-friendly error messages

9. Detecting Network State

Example: Check network status

import { Network } from &#x27;expo-network&#x27;;

export default function NetworkStatus() {
  const [networkState, setNetworkState] = useState(null);

  useEffect(() => {
    const checkNetwork = async () => {
      const state = await Network.getNetworkStateAsync();
      setNetworkState(state);
    };

    checkNetwork();
  }, []);

  return (
    <View style={styles.container}>
      <Text>Network Type: {networkState?.type || &#x27;Unknown&#x27;}</Text>
      <Text>Is Connected: {networkState?.isConnected ? &#x27;Yes&#x27; : &#x27;No&#x27;}</Text>
    </View>
  );
}
Property Description Values
type Network type detected "UNKNOWN", "ETHERNET", "WIFI", "CELLULAR", "NONE"
isConnected Whether device has network access true, false
isInternetReachable Whether device can reach the internet true, false, null (unknown)
Note: On Android, isInternetReachable may return null if the device is connected to a network that does not have internet access.
Warning: Network state can change dynamically. It's recommended to listen for changes using Network.addEventListener.

Example: Listen for network changes

import { Network } from &#x27;expo-network&#x27;;

const handleNetworkChange = (networkState) => {
  console.log("Network changed:", networkState);
};

Network.addEventListener("networkStateChange", handleNetworkChange);

// Don&#x27;t forget to remove listener when component unmounts
useEffect(() => {
  return () => {
    Network.removeEventListener("networkStateChange", handleNetworkChange);
  };
}, []);

10. Using WebSockets

Property Description Example
WebSocket URL URL to connect to the WebSocket server wss://example.com/websocket
Connection Status Indicates the state of the WebSocket connection OPEN, CLOSING, CLOSED

Example: Establishing a WebSocket Connection

import * as WebSocket from 'ws';

const ws = new WebSocket("wss://example.com/websocket");

ws.on("open", () => {
  console.log("Connected to WebSocket server");
});

ws.on("message", (data) => {
  console.log("Received:", data);
});

ws.on("close", () => {
  console.log("WebSocket connection closed");
});

Example: Sending Data via WebSocket

const message = {
  type: "chat",
  content: "Hello, server!"
};

ws.send(JSON.stringify(message));
Note: Ensure that your server supports WebSocket connections and that the URL uses wss:// for secure connections.
Warning: WebSocket connections may not work in all environments (e.g., some web browsers or network configurations). Always test in your target environment.

11. Implementing GraphQL

Example: Setting up a GraphQL client with Apollo

import { ApolloClient, InMemoryCache, ApolloProvider, useQuery } from '@apollo/client';
import { gql } from 'graphql-tag';

const client = new ApolloClient({
  uri: 'https://your-graphql-endpoint.com/graphql',
  cache: new InMemoryCache()
});

const GET_POSTS = gql`
  query GetPosts {
    posts {
      id
      title
      content
    }
  }
`;

function PostsList() {
  const { loading, error, data } = useQuery(GET_POSTS);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <ul>
      {data.posts.map(post => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}
Feature Description Notes
Apollo Client @apollo/client Popular GraphQL client for React and React Native
GraphQL Schema gql Used to define queries and mutations in JavaScript
Server Integration Expo supports GraphQL via HTTP clients Use fetch or axios for direct API calls
Note: Expo does not include built-in GraphQL support, but it works well with Apollo Client and other GraphQL libraries.

12. Caching API Requests

Property Description Default
cacheTTL Time-to-live for cached responses in milliseconds 300000
cacheKey Custom key to identify the cache entry null
enableCache Enable or disable caching for the request true

Example: Using cacheTTL

import { cache } from 'expo-api';\n\nconst response = await cache.fetch('https://api.example.com/data', {\n  cacheTTL: 60000,\n  method: 'GET'\n});
Note: Caching is particularly useful for API endpoints that return static or semi-static data, such as user profiles or configuration files.

Was this article helpful?