Building an Offline-First Notes App with React
This tutorial explains how to build a Note app in React that implements offline sync: allowing users to continue interacting with the app…
Building an Offline-First Notes App with React

This tutorial explains how to build a Note app in React that implements offline sync: allowing users to continue interacting with the app even when offline and automatically syncing their data when connectivity is restored.
If you haven't, I advise going through this article first to understand the purpose behind this tutorial: ***Building Resilient React Apps: Offline Sync for Unstable Networks***
Don’t worry, I’ll break it down into simple, easy-to-understand steps.

You can find the complete code in the GitHub repository linked below: https://github.com/qobitech/note-app-demo.git
Demo: https://note-app-demo.netlify.app/
Note: The code provided is for demonstration purposes and may need updates for production use. We have kept it simple to help junior developers understand the core concepts.
Overview
This React app allows users to:
- Write notes with a title and content
- Save notes both online and offline
- Automatically sync offline notes when back online
- Display saved notes and allow users to edit them
- Delete note(S)
Key Features in the Code
1. State Management
The app uses the useState hook to manage its data:
note: Stores the current note being edited.syncInProgress: Tracks whether notes are being synced online.
const [note, setNote] = useState<INote>({ ...defaultNote, id: uuidv4() })
const [syncInProgress, setSyncInProgress] = useState<boolean>(false)
2. Tracking Network Status
A custom hook useNetworkStatus() checks whether the user is online or offline.
const isOnline = useNetworkStatus()
3. Handling Offline Data
A second custom hook useSync() manages offline storage. It provides methods to:
- Save offline updates (
saveOfflineUpdate) - Retrieve stored offline notes (
getOfflineUpdates) - Clear synced offline notes (
clearOfflineUpdates) - Remove synced offline note item (
removeOfflineItem)
const { saveOfflineUpdate, getOfflineUpdates, clearOfflineUpdates } = useSync<INote[]>()
4. Saving Notes
When a note is saved:
- If online, it attempts to save the note to the server.
- If offline or saving fails, it stores the note locally.
/**
* Handles saving a note.
* - If online, it tries to save the note to the server.
* - If the request fails,if offline or online, it saves the note locally.
*/
const handleSaveNote = async (id: string, value: string) => {
if (!value.trim()) return // Prevent saving empty notes
if (note.id) {
const filteredNotes = offlineData?.filter((i) => i.id !== note.id) || []
const updatedNote = { ...note, [id]: value, timeStamp: Date.now() }
const modifiedNotes = [updatedNote, ...filteredNotes]
try {
// save note locally
await saveOfflineUpdate(modifiedNotes)
// save note to the server
if (isOnline) await saveNote(updatedNote) // Try saving online
} catch (error) {
console.error('Failed to save note:', error)
// Optionally add error handling or user notification
}
}
}
5. Debouncing User Input
To prevent excessive API calls, the handleDebouncedSaveNote function:
- Updates the note state immediately
- Waits 500ms before saving the note
const handleDebouncedSaveNote = (
e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => {
setNote((prev) => ({ ...prev, [e.target.id]: e.target.value }))
if (debounceTimeout.current) clearTimeout(debounceTimeout.current)
debounceTimeout.current = window.setTimeout(() => {
handleSaveNote(e.target.id, e.target.value) // Save after delay
}, 500)
}
6. Syncing Offline Notes When Online
When the app detects that the user is back online, it:
- Retrieves offline notes
- Saves them to the server
- Clears them from local storage if successful
useEffect(() => {
if (isOnline) {
(async () => {
const offlineNotes = await getOfflineUpdates()
if (offlineNotes.length > 0) {
try {
await Promise.all(offlineNotes.map(saveNote)) // Sync all offline notes
await clearOfflineUpdates() // Clear after sync
} catch {
console.error('Failed to sync offline notes')
}
}
})()
}
}, [isOnline])
7. Creating & Editing Notes
handleNewNote: Creates a new empty note.handleEditNote: Loads an existing note for editing.
const handleNewNote = useCallback(() => {
setNote({ ...defaultNote, id: uuidv4() })
}, [])
const handleEditNote = useCallback((note: INote) => {
setNote(note)
}, [])
8. Rendering Notes & UI Components
The app displays saved notes and provides UI for creating/editing them. The SavedNoteItem component renders each saved note.
<SavedNoteGridClass>
{notes.map((n) => (
<SavedNoteItem key={n.id} note={n} onClick={() => handleEditNote(n)} />
))}
</SavedNoteGridClass>
Summary
This Notes App is designed to work both online and offline, ensuring a seamless experience for users regardless of their internet connection.
Key Takeaways:
- State Management: Uses
useStatefor tracking notes and sync status. - Offline Handling: Saves notes locally when the user is offline.
- Debouncing: Prevents excessive API calls when typing.
- Syncing Mechanism: Detects when the user is back online and syncs saved notes.
By understanding these concepts, you can build more resilient applications that work even in unreliable network conditions!
메타데이터
- post_id
- df2d92e7a6c7
- slug
- building-an-offline-first-notes-app-with-react-df2d92e7a6c7
- url
- https://medium.com/@edekobifrank/building-an-offline-first-notes-app-with-react-df2d92e7a6c7
- canonical_url
- https://medium.com/@edekobifrank/building-an-offline-first-notes-app-with-react-df2d92e7a6c7
- author_url
- https://medium.com/@edekobifrank
- status
- ok
- fetched_at
- 2026-07-11 04:13:04