React Native Axios API Layer

Small apps call fetch directly inside screens. Growing apps repeat the same address, headers, and error handling in dozens of places. An API layer gathers all server communication into one organized module. Axios, a popular HTTP library, makes that module short, readable, and easy to maintain.

Why Build a Layer

Without a layer                With a layer
───────────────────            ──────────────────────────
Screen → server                Screen → api/products.js → client → server
Screen → server                Screen → api/users.js    → client → server
Screen → server                One place for URL, token, errors
Repeated code everywhere

Install Axios

npm install axios

Step 1: Create a Shared Client

An Axios instance stores the base address, timeout, and default headers. Every request inherits them.

// src/api/client.js
import axios from 'axios';

const client = axios.create({
  baseURL: 'https://api.example.com/v1',
  timeout: 10000,
  headers: { 'Content-Type': 'application/json' },
});

export default client;

Step 2: Write Endpoint Functions

Group related calls into files. Screens call a named function and never see URLs.

// src/api/products.js
import client from './client';

export const getProducts = async (page = 1) => {
  const { data } = await client.get('/products', { params: { page } });
  return data;
};

export const getProduct = async (id) => {
  const { data } = await client.get(`/products/${id}`);
  return data;
};

export const createProduct = async (product) => {
  const { data } = await client.post('/products', product);
  return data;
};

export const deleteProduct = (id) => client.delete(`/products/${id}`);

Axios turns the params object into a query string and converts JSON automatically, which removes manual parsing work.

Step 3: Attach the Token Automatically

A request interceptor runs before every call. Use it to add the sign-in token once.

import * as SecureStore from 'expo-secure-store';

client.interceptors.request.use(async (config) => {
  const token = await SecureStore.getItemAsync('token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});
Screen calls getProducts()
        │
        ▼
Request interceptor adds token
        │
        ▼
      Server
        │
        ▼
Response interceptor checks errors
        │
        ▼
Screen receives data

Step 4: Handle Errors in One Place

A response interceptor catches failures from every call. Translate technical errors into friendly messages.

client.interceptors.response.use(
  (response) => response,
  (error) => {
    if (!error.response) {
      return Promise.reject(new Error('No internet connection'));
    }
    if (error.response.status === 401) {
      signOutUser();
    }
    if (error.response.status >= 500) {
      return Promise.reject(new Error('Server problem. Try again soon.'));
    }
    return Promise.reject(error);
  }
);

Step 5: Use the Layer in a Screen

function ProductScreen() {
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');

  useEffect(() => {
    const load = async () => {
      try {
        setProducts(await getProducts());
      } catch (e) {
        setError(e.message);
      } finally {
        setLoading(false);
      }
    };
    load();
  }, []);

  if (loading) return <ActivityIndicator />;
  if (error) return <Text>{error}</Text>;
  return <FlatList data={products} renderItem={renderProduct} />;
}

Cancel Requests

A user may leave a screen before a request ends. An abort controller cancels the call and avoids updates on a closed screen.

useEffect(() => {
  const controller = new AbortController();
  client.get('/products', { signal: controller.signal });
  return () => controller.abort();
}, []);

Environment Addresses

Keep the base address in an environment variable so development and production point to different servers without code changes.

Axios or Fetch?

Feature               fetch         Axios
──────────────────────────────────────────
Built in              Yes           No (install)
Auto JSON parsing     Manual        Automatic
Interceptors          No            Yes
Timeout setting       Manual        Built in
Error on 4xx / 5xx    No            Yes

Summary

An API layer centralizes server communication. Create one Axios client with a base address and timeout, write endpoint functions per feature, attach tokens with a request interceptor, and translate failures with a response interceptor. Screens then stay clean and call simple named functions.