Your app works perfectly in the office.
Then your user takes the subway. Opens your app. Sees a spinner.
Nothing happens. They close it. Maybe forever.
The fix is simpler than you think.
Why This Matters
Your users are in elevators, basements, airplanes, rural areas, or just have bad signal.
If your app shows "No Internet Connection" and stops working, you're losing people.
The Simple Solution
You need three things:
- Know when offline - Detect network status
- Save data locally - Show something useful
- Sync when back online - Send queued actions
Let's build it.
Step 1: Detect Network Status
npm install @react-native-community/netinfo
Create a simple hook:
import NetInfo from '@react-native-community/netinfo';
import { useState, useEffect } from 'react';
export const useOnline = () => {
const [isOnline, setIsOnline] = useState(true);
useEffect(() => {
const unsubscribe = NetInfo.addEventListener(state => {
setIsOnline(state.isConnected);
});
return unsubscribe;
}, []);
return isOnline;
};
Now you know when to show cached data.
Step 2: Cache API Responses
When your API returns data, save it:
const fetchReports = async () => {
try {
const response = await fetch('/api/reports');
const data = await response.json();
// Save for offline use
await AsyncStorage.setItem('reports', JSON.stringify(data));
return data;
} catch (error) {
// Network failed - use cache
const cached = await AsyncStorage.getItem('reports');
return cached ? JSON.parse(cached) : [];
}
};
What happens:
Online: Fresh data from API
Offline: Last saved data
User always sees something
Step 3: Show Users What's Happening
Don't make them guess:
const ReportsScreen = () => {
const [reports, setReports] = useState([]);
const isOnline = useOnline();
useEffect(() => {
loadReports();
}, []);
return (
<View>
{!isOnline && (
<View style={styles.banner}>
<Text>📴 Offline - Showing saved data</Text>
</View>
)}
<FlatList data={reports} ... />
</View>
);
};
Simple banner. Users know what they're seeing.
Step 4: Queue Offline Actions
When users create something offline, save it and sync later:
const submitReport = async (data) => {
if (!isOnline) {
// Save locally
await AsyncStorage.setItem('pending_report', JSON.stringify(data));
Alert.alert('Saved offline. Will sync when online.');
return;
}
// Normal API call
await fetch('/api/reports', {
method: 'POST',
body: JSON.stringify(data),
});
};
Step 5: Auto-Sync When Online
Send queued data when connection returns:
useEffect(() => {
NetInfo.addEventListener(state => {
if (state.isConnected) {
syncPendingData(); // Send saved actions
}
});
}, []);
const syncPendingData = async () => {
const pending = await AsyncStorage.getItem('pending_report');
if (pending) {
await fetch('/api/reports', {
method: 'POST',
body: pending,
});
await AsyncStorage.removeItem('pending_report');
}
};
Real Example: Medical Records App
Imagine you're building a medical records app. Patients need to access their lab reports, but many live in areas with poor connectivity.
Here's how offline support helps:
const MedicalRecordsScreen = () => {
const [records, setRecords] = useState([]);
const isOnline = useOnline();
useEffect(() => {
loadRecords();
}, []);
const loadRecords = async () => {
// Load cache first (instant display)
const cached = await AsyncStorage.getItem('medical_records');
if (cached) setRecords(JSON.parse(cached));
// Then fetch fresh if online
if (isOnline) {
try {
const fresh = await fetch('/api/records').then(r => r.json());
setRecords(fresh);
await AsyncStorage.setItem('medical_records', JSON.stringify(fresh));
} catch (error) {
console.log('Using cached data');
}
}
};
return (
<View>
{!isOnline && (
<View style={styles.offlineBanner}>
<Text>📴 Offline Mode</Text>
</View>
)}
<FlatList
data={records}
renderItem={({ item }) => <RecordCard record={item} />}
/>
</View>
);
};
What users get:
- Instant access to their records (200ms from cache)
- Works in areas with no signal
- Fresh data syncs automatically when online
- No frustrating error screens
This same pattern works for:
- Shopping apps (cached products)
- News apps (saved articles)
- Todo apps (local tasks)
- Social apps (cached feed)
Quick Checklist
Before shipping:
- Show offline indicator
- Cache important data
- Queue offline actions
- Auto-sync when online
- Test in airplane mode
Common Mistakes
Don't do this:
if (!isOnline) {
throw new Error('No internet');
}
Do this:
if (!isOnline) {
return getCachedData();
}
When NOT to Cache
Some data shouldn't be cached:
❌ Banking transactions
❌ Live sports scores
❌ Stock prices
❌ Password reset tokens
For these, show "Requires internet connection" and don't fake it.
The Bottom Line
Offline support is three small changes:
- Cache responses
- Queue actions
- Tell users what's happening
Your app doesn't need perfect WiFi.
It needs to work when WiFi isn't perfect.
Try it: Add NetInfo to your app today. Cache one API response. See the difference.
What are you building? Drop a comment.
Top comments (0)