Most apps fetch data from APIs. React Native supports the standard fetch API and works well with libraries like TanStack Query.

Basic Fetch

  async function fetchUsers() {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    if (!response.ok) {
        throw new Error(`HTTP error: ${response.status}`);
    }
    return response.json();
}
  

Loading Data in a Component

  import { useState, useEffect } from 'react';
import { View, Text, ActivityIndicator, FlatList } from 'react-native';

function UserList() {
    const [users, setUsers] = useState([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
        fetchUsers()
            .then(setUsers)
            .catch((err) => setError(err.message))
            .finally(() => setLoading(false));
    }, []);

    if (loading) return <ActivityIndicator size="large" style={{ flex: 1 }} />;
    if (error) return <Text style={{ color: 'red', padding: 16 }}>Error: {error}</Text>;

    return (
        <FlatList
            data={users}
            keyExtractor={(item) => String(item.id)}
            renderItem={({ item }) => (
                <View style={{ padding: 16 }}>
                    <Text style={{ fontWeight: 'bold' }}>{item.name}</Text>
                    <Text>{item.email}</Text>
                </View>
            )}
        />
    );
}
  

POST Requests

  async function createPost(title, body) {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ title, body, userId: 1 }),
    });
    return response.json();
}
  

Authentication Headers

  async function fetchProtectedData(token) {
    const response = await fetch('https://api.example.com/data', {
        headers: {
            Authorization: `Bearer ${token}`,
            'Content-Type': 'application/json',
        },
    });
    return response.json();
}
  

Custom Hook Pattern

Extract fetch logic into a reusable hook:

  function useFetch(url) {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
        fetch(url)
            .then((res) => res.json())
            .then(setData)
            .catch((err) => setError(err.message))
            .finally(() => setLoading(false));
    }, [url]);

    return { data, loading, error };
}

// Usage:
const { data, loading, error } = useFetch('https://api.example.com/items');
  

Error Handling Best Practices

  • Always check response.ok before parsing JSON
  • Show user-friendly error messages, not raw stack traces
  • Retry failed requests with exponential backoff
  • Handle offline state gracefully

Next: access device features like camera, location, and local storage.