Understanding Axios Create: A Comprehensive Guide for Mobile Developers

Learn how to build reusable, configured HTTP clients for React Native and cross-platform mobile applications with best practices and code examples.

When building mobile applications with React Native or cross-platform frameworks, you'll often need to communicate with APIs and backend services. Managing HTTP requests efficiently becomes crucial as your app grows. This guide explores how axios.create helps you create reusable, configured HTTP clients tailored to your mobile app's specific needs.

Our web development services team regularly works with both mobile and web applications, and we've found that consistent API client patterns across platforms significantly reduce bugs and maintenance overhead. Whether you're building a consumer-facing app or an enterprise solution, understanding how to properly configure and reuse axios instances will save development time, reduce errors, and make your codebase more maintainable. We'll cover everything from basic configuration to advanced interceptor patterns that keep your authentication and error handling consistent across all API calls.

What is axios.create?

axios.create is a method that creates a new axios instance with a custom configuration. Instead of repeating the same configuration settings for every API call, you define them once and reuse the instance throughout your application.

The created instance has all the same methods as the default axios object--get, post, put, delete--but uses your custom configuration as defaults. This makes it ideal for mobile apps that need consistent API communication patterns across multiple screens and components.

Why Create Custom Instances?

When building mobile applications, you typically interact with multiple APIs or different endpoints of the same service. LogRocket's guide on axios.create explains that custom instances help you:

  • Avoid configuration repetition: Set base URLs, headers, and timeouts once, then reuse across all components
  • Maintain consistency: Ensure all requests to the same API use identical settings, reducing bugs
  • Improve organization: Separate concerns between different API services (auth, user data, content delivery)
  • Simplify testing: Mock or replace instances easily in your test suite without modifying component code

This approach aligns with best practices from our web development methodology, where we emphasize clean separation of concerns and reusable code patterns.

Basic syntax for creating a custom axios instance
1const instance = axios.create(config);2 3// Example: Create a configured instance4const api = axios.create({5 baseURL: 'https://api.example.com/v1',6 timeout: 10000,7 headers: {8 'Content-Type': 'application/json'9 }10});11 12// Use the instance like regular axios13api.get('/users'); // Uses configured baseURL and headers14api.post('/users', { name: 'John' }); // Same configuration applied

Core Configuration Options

The axios.create method accepts a configuration object that defines how all requests made with that instance should behave. Axios documentation covers all available options in detail, but let's explore the most important ones for mobile development.

baseURL

The baseURL is probably the most frequently used configuration option. It prepends to all relative URLs in your requests, eliminating the need to repeat the full API endpoint for every call. For mobile apps with a single backend service and multiple endpoint versions, this configuration is essential for maintaining clean, readable code.

As noted by Apidog's analysis of axios.create, baseURL configuration becomes especially valuable when your app consumes APIs from different services with different domain structures.

Setting baseURL for consistent API endpoints
1const api = axios.create({2 baseURL: 'https://api.example.com/v1'3});4 5// All requests automatically use the baseURL6api.get('/users'); // Request to: https://api.example.com/v1/users7api.get('/products'); // Request to: https://api.example.com/v1/products8api.post('/orders', { userId: 123 }); // Request to: https://api.example.com/v1/orders

timeout

The timeout setting specifies the number of milliseconds before a request times out. This is particularly important for mobile apps where network conditions vary significantly--from fast 5G connections to spotty cellular coverage.

Setting appropriate timeouts prevents your app from hanging indefinitely on slow or unreliable connections. Users on slower networks will appreciate immediate feedback rather than waiting indefinitely for responses that may never arrive.

Configuring request timeout for mobile networks
1const api = axios.create({2 timeout: 10000 // 10 seconds - good balance for most mobile requests3});4 5// Different services might need different timeouts6const mediaApi = axios.create({7 timeout: 30000 // 30 seconds for larger media uploads/downloads8});9 10const authApi = axios.create({11 timeout: 5000 // 5 seconds - auth should be fast12});

headers

Custom headers can be set globally for all requests made with an instance. Common use cases include:

  • Authentication tokens: Bearer tokens, API keys
  • Content negotiation: Accept and Content-Type headers
  • Custom metadata: App version, device type, platform information
  • Caching directives: Cache-control headers

This centralized header configuration ensures consistency across your entire mobile application, reducing the chance of forgotten headers causing API errors.

Setting custom headers for all requests
1const api = axios.create({2 headers: {3 'Content-Type': 'application/json',4 'Accept': 'application/json',5 'X-App-Version': '1.0.0',6 'X-Platform': Platform.OS // 'ios' or 'android'7 }8});9 10// All requests automatically include these headers11api.get('/users');12// Headers sent: Content-Type, Accept, X-App-Version, X-Platform, Authorization (if set)
Additional Configuration Options

axios.create supports many more options for fine-tuned control

params

URL parameters to include with every request

responseType

How to parse responses: 'json', 'text', 'blob', 'arraybuffer'

validateStatus

Function to determine which status codes trigger errors

maxRedirects

Maximum redirects to follow (default: 5)

decompress

Whether to decompress response bodies automatically

xsrf settings

CSRF protection with xsrfCookieName and xsrfHeaderName

Creating Instances for Different Services

When your mobile app communicates with multiple services, create separate instances for each. This separation makes your code more maintainable and allows different configurations per service.

For example, your authentication API might need shorter timeouts than your content delivery API handling large media files. Different services might also require different authentication mechanisms or headers.

Creating separate axios instances for different services
1// Authentication API - fast, short timeouts2const authApi = axios.create({3 baseURL: 'https://auth.example.com',4 timeout: 5000,5 headers: {6 'Content-Type': 'application/json'7 }8});9 10// User data API - moderate timeouts11const userApi = axios.create({12 baseURL: 'https://api.example.com/users',13 timeout: 10000,14 headers: {15 'Content-Type': 'application/json'16 }17});18 19// Content API - longer timeouts for media20const contentApi = axios.create({21 baseURL: 'https://cdn.example.com',22 timeout: 30000,23 headers: {24 'Accept': 'application/octet-stream'25 }26});

Environment-Based Configuration

Mobile apps often need different configurations for development, staging, and production environments. Apidog's guide demonstrates that by creating a factory function that returns appropriately configured instances, you can seamlessly switch between environments while maintaining consistent code patterns throughout your application.

This approach is essential for apps that need to connect to local development servers during development but production APIs in live deployments.

Environment-based API configuration factory
1// api/factory.js2const createApiClient = (env = 'development') => {3 const configs = {4 development: {5 baseURL: 'http://localhost:3000/api',6 timeout: 50007 },8 staging: {9 baseURL: 'https://staging-api.example.com',10 timeout: 1000011 },12 production: {13 baseURL: 'https://api.example.com',14 timeout: 1500015 }16 };17 18 const config = configs[env] || configs.development;19 20 return axios.create(config);21};22 23// Usage24const api = createApiClient(__DEV__ ? 'development' : 'production');

Working with Interceptors

Interceptors are one of the most powerful features of axios instances. They allow you to run code before requests are sent and before responses are returned to your calling code.

Request Interceptors

Request interceptors run before each request is sent, allowing you to modify configurations or add data. This is ideal for automatically adding authentication tokens to every request without repeating the token retrieval logic throughout your codebase.

The interceptor pattern keeps authentication logic centralized and consistent. When you need to change how tokens are retrieved or refreshed, you only need to update one place.

Request interceptor for automatic token injection
1const api = axios.create({2 baseURL: 'https://api.example.com'3});4 5// Add auth token to every request automatically6api.interceptors.request.use(7 async (config) => {8 // Get token from secure storage9 const token = await SecureStore.getItemAsync('authToken');10 11 if (token) {12 config.headers.Authorization = `Bearer ${token}`;13 }14 15 return config;16 },17 (error) => {18 // Handle interceptor errors19 return Promise.reject(error);20 }21);22 23// Now all api calls automatically include the Bearer token

Response Interceptors

Response interceptors handle responses before they're returned to your calling code. Use them to implement global error handling, response transformation, or automatic token refresh.

For mobile apps, this is crucial for handling common error scenarios like 401 unauthorized responses that require logging the user out and redirecting to the login screen.

Response interceptor for global error handling
1api.interceptors.response.use(2 (response) => {3 // Transform successful responses before returning4 return {5 ...response,6 data: transformResponse(response.data)7 };8 },9 (error) => {10 // Handle errors globally11 if (error.response?.status === 401) {12 // Token expired or invalid - clear storage and navigate to login13 SecureStore.deleteItemAsync('authToken');14 NavigationService.navigate('Login');15 } else if (error.response?.status === 500) {16 // Server error - show appropriate feedback17 showErrorNotification('Something went wrong. Please try again.');18 }19 20 return Promise.reject(error);21 }22);

Common Error Handling Patterns for Mobile

LogRocket's best practices guide highlights several error patterns that mobile apps should handle:

  • Timeout errors (ECONNABORTED): Show user-friendly messages and offer retry options
  • Network errors: Check navigator.onLine and provide offline UI
  • Rate limiting: Handle 429 responses with backoff strategies
  • Server errors: Provide graceful degradation when APIs are unavailable

Implementing these patterns in a response interceptor ensures consistent behavior across all API calls in your app.

Comprehensive error handling patterns for mobile
1api.interceptors.response.use(2 (response) => response,3 (error) => {4 // Handle timeout specifically5 if (error.code === 'ECONNABORTED') {6 showNotification('Request timed out. Please try again.');7 }8 9 // Handle offline state10 if (!navigator.onLine) {11 showOfflineMessage();12 // Queue request for retry when back online13 queueRequestForRetry(error.config);14 }15 16 // Handle rate limiting17 if (error.response?.status === 429) {18 const retryAfter = error.response.headers['retry-after'] || 60;19 scheduleRetry(error.config, retryAfter);20 }21 22 return Promise.reject(error);23 }24);

Practical Examples for Mobile Development

Let's put everything together in a complete React Native API client implementation that demonstrates best practices for production mobile apps.

Complete React Native API client with auth handling
1// api/client.js2import axios from 'axios';3import AsyncStorage from '@react-native-async-storage/async-storage';4 5const createApiClient = (baseURL, timeout = 10000) => {6 const client = axios.create({7 baseURL,8 timeout,9 headers: {10 'Content-Type': 'application/json',11 'Accept': 'application/json'12 }13 });14 15 // Request interceptor for auth16 client.interceptors.request.use(17 async (config) => {18 const token = await AsyncStorage.getItem('authToken');19 if (token) {20 config.headers.Authorization = `Bearer ${token}`;21 }22 return config;23 },24 (error) => Promise.reject(error)25 );26 27 // Response interceptor for error handling28 client.interceptors.response.use(29 (response) => response,30 (error) => {31 if (error.response?.status === 401) {32 // Clear storage and navigate to login33 AsyncStorage.clear();34 NavigationService.navigate('Login');35 }36 return Promise.reject(error);37 }38 );39 40 return client;41};42 43export const api = createApiClient('https://api.example.com');

Handling Multiple Concurrent Requests

For features like dashboard screens that need to refresh multiple data points simultaneously, use Promise.all with your different API instances. This pattern is common in mobile apps where you need to fetch user data, notifications, and activity feed concurrently for a snappy user experience.

By structuring your API calls to run in parallel, you reduce the total wait time compared to sequential requests.

Fetching multiple data sources concurrently
1// Fetch dashboard data from multiple sources concurrently2const fetchDashboardData = async () => {3 try {4 const [userResponse, notificationsResponse, feedResponse] = await Promise.all([5 userApi.get('/current'),6 notificationsApi.get('/unread'),7 feedApi.get('/recent')8 ]);9 10 return {11 user: userResponse.data,12 notifications: notificationsResponse.data,13 feed: feedResponse.data14 };15 } catch (error) {16 console.error('Failed to fetch dashboard data:', error);17 throw error;18 }19};20 21// Usage in a React component22useEffect(() => {23 const loadData = async () => {24 const data = await fetchDashboardData();25 setDashboardData(data);26 };27 loadData();28}, []);

Canceling Requests

Mobile apps frequently need to cancel pending requests when users navigate away from a screen. Using AbortController with axios cancel tokens prevents memory leaks and unnecessary network activity when components unmount.

This is especially important in navigation-heavy apps where users might quickly move between screens, causing multiple requests to become irrelevant.

Canceling requests with AbortController
1// API function that accepts a cancel token2const fetchUserProfile = (userId, cancelToken) => {3 return userApi.get(`/profiles/${userId}`, {4 cancelToken5 });6};7 8// In a React component using useEffect for cleanup9useEffect(() => {10 const controller = new AbortController();11 12 const loadProfile = async () => {13 try {14 const response = await fetchUserProfile(userId, controller.signal);15 setProfile(response.data);16 } catch (error) {17 if (error.name === 'CanceledError') {18 // Request was canceled - this is expected19 console.log('Request canceled');20 } else {21 // Real error occurred22 setError(error);23 }24 }25 };26 27 loadProfile();28 29 // Cleanup: cancel request when component unmounts30 return () => controller.abort();31}, [userId]);
Best Practices for Mobile Apps

Key considerations for production-ready mobile API clients

Appropriate Timeouts

3-5 seconds for interactive features, 15-30 seconds for background operations

Offline Handling

Queue requests for retry or show offline UI when network is unavailable

Automatic Retries

Implement exponential backoff for critical operations with 3 retry attempts

Response Caching

Cache frequently accessed data to reduce network calls and improve perceived performance

Separate API Concerns by Domain

Create dedicated instances for authentication, user data, and media content with appropriate timeouts and configurations for each. This separation makes debugging easier and allows each service to evolve independently as your app grows.

For example, media uploads might need much longer timeouts than authentication requests, and payment processing might require additional security headers that other services don't need.

Separating API concerns by domain
1// services/api/auth.js2export const authApi = axios.create({3 baseURL: 'https://auth.example.com',4 timeout: 5000 // Auth should be fast5});6 7// services/api/users.js8export const usersApi = axios.create({9 baseURL: 'https://api.example.com/users',10 timeout: 1000011});12 13// services/api/media.js14export const mediaApi = axios.create({15 baseURL: 'https://cdn.example.com',16 timeout: 60000 // Longer timeout for uploads17});18 19// services/api/payments.js20export const paymentsApi = axios.create({21 baseURL: 'https://payments.example.com',22 timeout: 30000,23 headers: {24 'X-Payment-Signature': getPaymentSignature()25 }26});

Common Patterns and Anti-Patterns

Conclusion

axios.create is a powerful tool for managing HTTP requests in mobile applications. By creating custom instances with appropriate configurations, you can:

  • Reduce code duplication by defining configuration once and reusing instances
  • Improve maintainability by centralizing API client logic
  • Centralize cross-cutting concerns like authentication and error handling
  • Handle mobile-specific challenges like offline states and variable network conditions

Start by identifying the different API services your app communicates with, then create dedicated instances for each with appropriate timeouts and headers. Use interceptors to handle authentication, logging, and error management consistently across all requests.

For teams building cross-platform mobile applications, investing time in proper axios instance setup pays dividends in code quality, debugging ease, and user experience. The patterns covered in this guide are battle-tested approaches used in production mobile apps.

If your mobile app requires integration with AI-powered features, our AI automation services team can help you implement intelligent API patterns that enhance user experience. Looking to build a robust mobile application with clean, maintainable API integration? Our mobile development team has extensive experience building React Native and cross-platform applications with best-practice API architectures.

Ready to Build a Robust Mobile Application?

Our team specializes in React Native and cross-platform mobile development with production-ready API architectures.

Sources

  1. LogRocket Blog - Understanding axios.create - Comprehensive guide covering why and how to use axios.create with practical examples
  2. Axios Documentation - The Axios Instance - Official documentation on creating axios instances
  3. Axios Documentation - Getting Started - Official introduction to axios features
  4. Apidog Blog - Boost Your Productivity: How axios.create Simplifies API Integration - Real-world examples and best practices