How to add offline support in React
Offline support enables React applications to work without internet connectivity by caching resources and data locally. As the creator of CoreUI with 12 years of React development experience, I’ve built offline-first React applications serving millions of users globally.
The most reliable approach combines service workers for asset caching with local storage or IndexedDB for data persistence.
Setup Service Worker
First, ensure you have a service worker configured (see how to add service workers in React).
Update public/service-worker.js for offline caching:
import { precacheAndRoute, createHandlerBoundToURL } from 'workbox-precaching'
import { registerRoute } from 'workbox-routing'
import { NetworkFirst, CacheFirst, StaleWhileRevalidate } from 'workbox-strategies'
precacheAndRoute(self.__WB_MANIFEST)
// Cache HTML pages
registerRoute(
({ request }) => request.mode === 'navigate',
new NetworkFirst({
cacheName: 'pages',
networkTimeoutSeconds: 3
})
)
// Cache API responses
registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new NetworkFirst({
cacheName: 'api-cache',
networkTimeoutSeconds: 5
})
)
// Cache static assets
registerRoute(
({ request }) => ['style', 'script', 'image'].includes(request.destination),
new CacheFirst({
cacheName: 'assets'
})
)
Create Offline Hook
Create src/hooks/useOffline.js:
import { useState, useEffect } from 'react'
export const useOffline = () => {
const [isOffline, setIsOffline] = useState(!navigator.onLine)
useEffect(() => {
const handleOnline = () => setIsOffline(false)
const handleOffline = () => setIsOffline(true)
window.addEventListener('online', handleOnline)
window.addEventListener('offline', handleOffline)
return () => {
window.removeEventListener('online', handleOnline)
window.removeEventListener('offline', handleOffline)
}
}, [])
return isOffline
}
Create Offline Storage Service
Create src/services/offlineStorage.js:
const STORAGE_KEY = 'offline_data'
export const offlineStorage = {
save: (key, data) => {
const store = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}')
store[key] = {
data,
timestamp: Date.now()
}
localStorage.setItem(STORAGE_KEY, JSON.stringify(store))
},
get: (key) => {
const store = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}')
return store[key]?.data || null
},
remove: (key) => {
const store = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}')
delete store[key]
localStorage.setItem(STORAGE_KEY, JSON.stringify(store))
},
clear: () => {
localStorage.removeItem(STORAGE_KEY)
}
}
Create Offline-Aware Fetch
Create src/utils/offlineFetch.js:
import { offlineStorage } from '../services/offlineStorage'
export const offlineFetch = async (url, options = {}) => {
try {
const response = await fetch(url, options)
const data = await response.json()
offlineStorage.save(url, data)
return data
} catch (error) {
if (!navigator.onLine) {
const cachedData = offlineStorage.get(url)
if (cachedData) {
return cachedData
}
}
throw error
}
}
Use in Component
import React, { useState, useEffect } from 'react'
import { useOffline } from './hooks/useOffline'
import { offlineFetch } from './utils/offlineFetch'
function App() {
const [data, setData] = useState([])
const [error, setError] = useState(null)
const isOffline = useOffline()
useEffect(() => {
const fetchData = async () => {
try {
const result = await offlineFetch('/api/data')
setData(result)
} catch (err) {
setError('Failed to load data')
}
}
fetchData()
}, [])
return (
<div>
{isOffline && (
<div className="offline-banner">
You are offline. Showing cached data.
</div>
)}
{error && <div className="error">{error}</div>}
<ul>
{data.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
)
}
export default App
Best Practice Note
This is the same offline strategy we use in CoreUI’s React PWA templates. The combination of service workers for asset caching and local storage for data ensures your app works seamlessly offline. For larger datasets, consider using IndexedDB instead of localStorage.
For production applications, consider using CoreUI’s React Admin Template which includes pre-built offline support, background sync, and conflict resolution.
Related Articles
For complete PWA functionality, you might also want to learn how to add push notifications in React to re-engage users when they come back online.



