Making HTTP Requests
Most mobile apps need to fetch data from servers — user profiles, product lists, news feeds, weather data, and more. React Native provides the fetch API for making HTTP requests. It works just like the fetch API in web browsers, so if you've done web development, you already know how to use it.
Fetch is promise-based, meaning it returns a promise that resolves with the response. You handle the result using .then() and .catch() or async/await syntax.
GET Requests
A GET request fetches data from a server. It's the most common type of HTTP request.
import React, { useState, useEffect } from 'react';
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(data => {
setUsers(data);
setLoading(false);
})
.catch(err => {
setError(err.message);
setLoading(false);
});
}, []);
if (loading) return <ActivityIndicator size="large" />;
if (error) return <Text>Error: {error}</Text>;
return (
<FlatList
data={users}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => (
<View style={{ padding: 20, borderBottomWidth: 1 }}>
<Text style={{ fontSize: 18 }}>{item.name}</Text>
<Text style={{ color: 'gray' }}>{item.email}</Text>
</View>
)}
/>
);
}
export default UserList;
The flow is straightforward: call fetch with the URL, parse the JSON response, and update your state. Always handle loading and error states — network requests can take time and sometimes fail. Users should see a loading indicator while waiting and a helpful message if something goes wrong.
POST Requests
A POST request sends data to the server. You use it for creating new resources — submitting a form, posting a comment, or registering a user.
const createUser = async (userData) => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: userData.name,
email: userData.email,
}),
});
const result = await response.json();
return result;
} catch (error) {
console.error('Error creating user:', error);
throw error;
}
};
// Usage
createUser({ name: 'John', email: 'john@example.com' })
.then(newUser => console.log('Created:', newUser));
For POST requests, you pass an options object to fetch with the method, headers, and body. The body must be a string, so use JSON.stringify to convert your object. Always set the Content-Type header to application/json so the server knows how to parse the data.
Async/Await Syntax
While .then() chains work fine, async/await makes asynchronous code easier to read and write. It looks like regular synchronous code but doesn't block the main thread.
async function fetchPosts() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const posts = await response.json();
return posts;
} catch (error) {
console.error('Failed to fetch posts:', error);
return [];
}
}
The async keyword goes before the function declaration. await pauses the function until the promise resolves. Always wrap await calls in try/catch blocks to handle errors gracefully. This pattern is cleaner and less error-prone than chaining .then() calls.