Skip to main content

React Native REST API Integration: Fetch, Post, and Optimize with Axios

· 10 min read
Mobile Developer
Last updated on August 23, 2025

rest api integration intro

Note: This guide uses React Native 0.75.4 and Expo SDK 51, which remain supported as of August 2025 for projects needing RN 0.75 compatibility. Expo SDK 53 offers improved features, including enhanced New Architecture support. Check reactnative.dev and docs.expo.dev for updates if using newer versions like React Native 0.76 or Expo SDK 53.

Tooling Compatibility Matrix

ToolVersionNotes
React Native0.75.4Compatible with Expo SDK 51
Expo~51.0.0Supports EAS Build/Update, New Architecture
Node.js20.x (LTS)Required for EAS CLI
Xcode16+iOS 18 SDK, macOS only
Android Studio2024.3.2+Android SDK 35, NDK r25+
Axios1.11.0For REST API calls, improved over 1.7.2

Integrating REST APIs into your React Native app enables dynamic data fetching, like user profiles or posts, for an engaging user experience. This beginner-friendly guide shows you how to integrate REST APIs in React Native 0.75.4 with Expo SDK 51, using Axios for data fetching, posting, and error handling. Expo SDK 51 supports React Native’s New Architecture, including bridgeless mode, for better performance. We’ll ensure compatibility with iOS (Xcode 16+, iOS 18 SDK) and Android (SDK 35), using TypeScript for type safety and EAS Update for deployment. If upgrading to newer React Native versions, see the React Native upgrade guide. For prebuilt API-integrated templates, check out Instamobile or Dopebase.

Let’s build a robust API-connected app!


Prerequisites

Ensure you have:

  • Node.js (v20.x or later, LTS): nodejs.org
  • npm (v10.x or later)
  • EAS CLI: For Expo management
  • Android Studio (2024.3.2+): Android SDK 35, NDK r25+
  • Xcode (16+): iOS 18 SDK (macOS only)
  • VS Code or similar editor
  • Git: For version control
  • A React Native project (Expo SDK 51)
  • A REST API endpoint (e.g., jsonplaceholder.typicode.com)
  • macOS: For iOS builds

What is a REST API? A REST API (Representational State Transfer) allows apps to communicate with servers using HTTP methods like GET and POST to fetch or send data. Learn more in React Native’s networking guide.


Step 1: Set Up Your Project

Create a React Native project with TypeScript and configure it for API integration.

1.1 Create Project

Install EAS CLI:

npm install -g eas-cli

Create a project:

npx create-expo-app MyApp --template blank-typescript

Navigate to the project:

cd MyApp

1.2 Configure app.config.js

Update app.config.js for flexibility and OTA updates:

export default () => ({
name: "MyApp",
slug: "myapp",
version: "1.0.0",
orientation: "portrait",
icon: ".https://docs.instamobile.io/assets/icon.png",
splash: {
image: ".https://docs.instamobile.io/assets/splash.png",
resizeMode: "contain",
backgroundColor: "#ffffff"
},
ios: {
bundleIdentifier: "com.myapp.app",
buildNumber: "1.0.0"
},
android: {
package: "com.myapp.app",
versionCode: 1
},
updates: {
enabled: true,
url: "https://u.expo.dev/your-project-id",
checkAutomatically: "ON_LOAD",
fallbackToCacheTimeout: 0
}
});

1.3 Test Locally

Run the app:

npx expo start

Press i for iOS or a for Android to verify setup.


Mega Bundle Sale is ON! Get ALL of our React Native codebases at 90% OFF discount 🔥

Get the Mega Bundle

Step 2: Fetch Data with GET

Set up Axios setup to fetch data from a REST API.

2.1 Install Axios

Add Axios for HTTP requests:

npm install [email protected]

What is Axios? Axios is a promise-based HTTP client for API calls, offering simpler syntax and better error handling than fetch. See Axios documentation.

2.2 Create API Service

Create src/api/api.ts to manage API calls:

import axios, { AxiosInstance } from 'axios';

const api: AxiosInstance = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com',
timeout: 10000,
});

export const getPosts = async () => {
const response = await api.get('/posts');
return response.data;
};

export const createPost = async (post: { title: string; body: string; userId: number }) => {
const response = await api.post('/posts', post);
return response.data;
};

2.3 Fetch Data in Component

Update src/App.tsx to fetch posts:

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

type Post = { id: number; title: string; body: string; userId: number };

export default function App() {
const [posts, setPosts] = useState<Post[]>([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
const fetchPosts = async () => {
try {
const data = await getPosts();
setPosts(data);
} catch (error) {
console.error('Error fetching posts:', error);
} finally {
setLoading(false);
}
};
fetchPosts();
}, []);

return (
<View style={{ flex: 1, padding: 20 }}>
{loading ? (
<Text>Loading...</Text>
) : (
<FlatList
data={posts}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => <Text>{item.title}</Text>}
/>
)}
</View>
);
}

Step 3: Post Data to API

Send data using POST requests.

3.1 Create Post Form

Update src/App.tsx to include a form:

import { useEffect, useState } from 'react';
import { View, Text, FlatList, TextInput, Button } from 'react-native';
import { getPosts, createPost } from './api/api';

type Post = { id: number; title: string; body: string; userId: number };

export default function App() {
const [posts, setPosts] = useState<Post[]>([]);
const [loading, setLoading] = useState(true);
const [title, setTitle] = useState('');
const [body, setBody] = useState('');

useEffect(() => {
const fetchPosts = async () => {
try {
const data = await getPosts();
setPosts(data);
} catch (error) {
console.error('Error fetching posts:', error);
} finally {
setLoading(false);
}
};
fetchPosts();
}, []);

const handleSubmit = async () => {
try {
const newPost = await createPost({ title, body, userId: 1 });
setPosts([newPost, ...posts]);
setTitle('');
setBody('');
} catch (error) {
console.error('Error creating post:', error);
}
};

return (
<View style={{ flex: 1, padding: 20 }}>
<TextInput
style={{ borderWidth: 1, marginBottom: 10, padding: 8 }}
placeholder="Post Title"
value={title}
onChangeText={setTitle}
/>
<TextInput
style={{ borderWidth: 1, marginBottom: 10, padding: 8 }}
placeholder="Post Body"
value={body}
onChangeText={setBody}
/>
<Button title="Submit Post" onPress={handleSubmit} />
{loading ? (
<Text>Loading...</Text>
) : (
<FlatList
data={posts}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => <Text>{item.title}</Text>}
/>
)}
</View>
);
}

Step 4: Implement Error Handling

Add robust error handling for API calls.

4.1 Enhance API Service

Update src/api/api.ts for error handling:

import axios, { AxiosInstance, AxiosError } from 'axios';

const api: AxiosInstance = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com',
timeout: 10000,
});

export const getPosts = async () => {
try {
const response = await api.get('/posts');
return response.data;
} catch (error) {
const axiosError = error as AxiosError;
throw new Error(axiosError.response?.data || 'Failed to fetch posts');
}
};

export const createPost = async (post: { title: string; body: string; userId: number }) => {
try {
const response = await api.post('/posts', post);
return response.data;
} catch (error) {
const axiosError = error as AxiosError;
throw new Error(axiosError.response?.data || 'Failed to create post');
}
};

4.2 Display Errors in UI

Update src/App.tsx to show errors:

import { useEffect, useState } from 'react';
import { View, Text, FlatList, TextInput, Button, Alert } from 'react-native';
import { getPosts, createPost } from './api/api';

type Post = { id: number; title: string; body: string; userId: number };

export default function App() {
const [posts, setPosts] = useState<Post[]>([]);
const [loading, setLoading] = useState(true);
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
const [error, setError] = useState<string | null>(null);

useEffect(() => {
const fetchPosts = async () => {
try {
const data = await getPosts();
setPosts(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchPosts();
}, []);

const handleSubmit = async () => {
try {
const newPost = await createPost({ title, body, userId: 1 });
setPosts([newPost, ...posts]);
setTitle('');
setBody('');
setError(null);
} catch (err) {
setError(err.message);
Alert.alert('Error', err.message);
}
};

return (
<View style={{ flex: 1, padding: 20 }}>
{error && <Text style={{ color: 'red' }}>{error}</Text>}
<TextInput
style={{ borderWidth: 1, marginBottom: 10, padding: 8 }}
placeholder="Post Title"
value={title}
onChangeText={setTitle}
/>
<TextInput
style={{ borderWidth: 1, marginBottom: 10, padding: 8 }}
placeholder="Post Body"
value={body}
onChangeText={setBody}
/>
<Button title="Submit Post" onPress={handleSubmit} />
{loading ? (
<Text>Loading...</Text>
) : (
<FlatList
data={posts}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => <Text>{item.title}</Text>}
/>
)}
</View>
);
}

Step 5: Test API Integration

Verify API integration with automated and manual tests.

5.1 Set Up Automated Tests

Install testing dependencies:

npm install --save-dev jest @types/jest ts-jest @testing-library/react-native @testing-library/jest-native

Configure package.json:

{
"scripts": {
"test": "jest"
},
"jest": {
"preset": "react-native",
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"setupFilesAfterEnv": ["@testing-library/jest-native/extend-expect"]
}
}

Add test in src/__tests__/App.test.tsx:

import { render, waitFor } from '@testing-library/react-native';
import App from '../App';
import { getPosts } from '../api/api';
import axios from 'axios';

jest.mock('axios');

test('renders posts from API', async () => {
const mockPosts = [{ id: 1, title: 'Test Post', body: 'Test Body', userId: 1 }];
axios.get.mockResolvedValue({ data: mockPosts });
const { getByText } = render(<App />);
await waitFor(() => expect(getByText('Test Post')).toBeTruthy());
});

Run tests:

npm test

5.2 Manual Testing

Test on iOS/Android devices to verify API calls, UI updates, and error messages.


Step 6: Deploy with OTA Updates

Deploy API updates with EAS Update.

6.1 Configure OTA

Install expo-updates:

npm install expo-updates

Check compatibility at docs.expo.dev.

Ensure app.config.js includes OTA settings (Step 1.2).

Update src/App.tsx for OTA updates:

import { useEffect, useState } from 'react';
import { View, Text, FlatList, TextInput, Button, Alert } from 'react-native';
import * as Updates from 'expo-updates';
import { getPosts, createPost } from './api/api';

type Post = { id: number; title: string; body: string; userId: number };

export default function App() {
const [posts, setPosts] = useState<Post[]>([]);
const [loading, setLoading] = useState(true);
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
const [error, setError] = useState<string | null>(null);

useEffect(() => {
const checkForUpdates = async () => {
try {
const update = await Updates.checkForUpdateAsync();
if (update.isAvailable) {
await Updates.fetchUpdateAsync();
await Updates.reloadAsync();
}
} catch (e) {
console.error('Update check failed:', e);
}
};
if (!__DEV__) {
checkForUpdates();
}

const fetchPosts = async () => {
try {
const data = await getPosts();
setPosts(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchPosts();
}, []);

const handleSubmit = async () => {
try {
const newPost = await createPost({ title, body, userId: 1 });
setPosts([newPost, ...posts]);
setTitle('');
setBody('');
setError(null);
} catch (err) {
setError(err.message);
Alert.alert('Error', err.message);
}
};

return (
<View style={{ flex: 1, padding: 20 }}>
{error && <Text style={{ color: 'red' }}>{error}</Text>}
<TextInput
style={{ borderWidth: 1, marginBottom: 10, padding: 8 }}
placeholder="Post Title"
value={title}
onChangeText={setTitle}
/>
<TextInput
style={{ borderWidth: 1, marginBottom: 10, padding: 8 }}
placeholder="Post Body"
value={body}
onChangeText={setBody}
/>
<Button title="Submit Post" onPress={handleSubmit} />
{loading ? (
<Text>Loading...</Text>
) : (
<FlatList
data={posts}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => <Text>{item.title}</Text>}
/>
)}
</View>
);
}

6.2 Publish Update

Configure EAS Update:

eas update:configure

Publish:

eas update --branch production

Test with a preview build:

eas build --profile preview --platform all

Troubleshooting Tips

  • API Errors: Verify network and endpoint. Log errors with console.error.
  • Dependency Issues: Run npm list and update per Expo’s compatibility guide.
  • Build Fails: Ensure Xcode 16+ and Android SDK 35. Clear caches (rm -rf ~/Library/Developer/Xcode/DerivedData or ./gradlew clean).
  • OTA Issues: Verify EXPO_TOKEN and app.config.js’s updates.url. Run eas update:configure.

End-of-Article Recap

You’ve learned to:

  • Perform Axios setup for API calls in a React Native project.
  • Fetch and post data with robust error handling.
  • Test and deploy updates via EAS Update, leveraging Expo SDK 51’s New Architecture support.

Quick Reference Checklist

  • Create project with npx create-expo-app MyApp --template blank-typescript.
  • Configure app.config.js with OTA settings.
  • Install Axios (npm install [email protected]) for data fetching.
  • Create API service in src/api/api.ts for GET and POST.
  • Implement form for posting data in src/App.tsx.
  • Add error handling with try-catch and UI alerts.
  • Set up Jest tests for API calls.
  • Deploy updates with EAS Update (eas update --branch production).

Looking for a custom mobile application?

Our team of expert mobile developers can help you build a custom mobile app that meets your specific needs.

Get in Touch

Conclusion

You’ve integrated REST APIs into your React Native 0.75.4 app with Expo SDK 51, using Axios 1.11.0 for efficient data handling and EAS Update for deployment. For projects upgrading to newer React Native versions, see the React Native upgrade guide. For prebuilt API-integrated templates, explore Instamobile or Dopebase. Dive deeper with Expo’s documentation or join the community at reactnative.dev.

Additionasl Resources