0Pricing
React Academy · Lesson

Building a Real-Time Notification Feed

Combine SSE with React state to build a notification feed that updates in real time without user interaction.

Building a Real-Time Notification Feed is a free React Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Notification Feed Architecture

A real-time notification feed combines an SSE stream for incoming notifications with REST endpoints for marking items as read. The component maintains local state for the notification list, subscribes to the server stream via EventSource in a useEffect, and handles user interactions (mark-as-read, dismiss) with optimistic updates.

Notification Data Shape

A notification object typically has this shape: { id: string, type: 'info' | 'warning' | 'success', message: string, timestamp: string, read: boolean }. The type field drives the icon and color. The read field tracks whether the user has acknowledged the notification. The timestamp enables grouping by time period.

Subscribing to the SSE Stream

In a useEffect, create an EventSource connected to /api/notifications/stream. On each message event, parse the JSON and prepend the new notification to state: setNotifications(prev => [JSON.parse(e.data), ...prev]). Prepending (unshift behavior) puts the newest notification at the top, which is standard for notification feeds.

Unread Count Badge

Derive the unread count from the notifications array without additional state: const unreadCount = notifications.filter(n => !n.read).length. Display this as a badge on the notification bell icon. The count updates automatically whenever the notifications state changes — no separate state management needed.

Marking as Read with Optimistic Update

When the user clicks a notification, apply an optimistic read update immediately: setNotifications(prev => prev.map(n => n.id === id ? { ...n, read: true } : n)). Then send a PATCH request to /api/notifications/:id with { read: true } in the background. Rollback the optimistic update if the request fails.

Grouping Notifications by Time

Group notifications for display: "Today" (same calendar day), "Yesterday", and "Older". Compute the group using the notification's timestamp and the current date: const today = new Date().toDateString(). Render each group as a separate section with a header label. This makes scanning a long notification list much easier.

Toast Notifications for Background Activity

When the user is on a different page and a new notification arrives via SSE, show a toast instead of (or in addition to) updating the notification list. Use a global notification context or Zustand store that both the SSE subscriber and the toast renderer can access. The toast disappears after a few seconds; the notification persists in the list.

Global Notification Context

For notifications that appear across the whole app, store them in a React context or Zustand store at the app root level. The SSE subscription lives in a provider component near the top of the tree. Any component can read notifications or dispatch new ones via the shared store, enabling toast rendering from any page.

SSE Reconnection on Tab Focus

EventSource automatically handles reconnection when the network drops, but tab visibility changes are different. When the user switches back to a tab after a long absence, the SSE connection may have been terminated by the server. EventSource reconnects automatically — and the Last-Event-ID mechanism replays any notifications the user missed while the tab was backgrounded.

Persisting Notifications Across Navigation

Single-page applications lose in-memory notification state when navigating away from the page. Store notifications in localStorage after each update: localStorage.setItem('notifications', JSON.stringify(notifications)). On mount, initialize state from localStorage before the SSE stream connects. This preserves the notification history across page navigation.

SSE Endpoint Pattern

The server-side SSE endpoint must set specific headers: Content-Type: text/event-stream, Cache-Control: no-cache, and Connection: keep-alive. In Express/NestJS, write events as data: ${JSON.stringify(payload)} — note the double newline which signals the end of an event. The server must flush after each write to ensure the browser receives the event immediately.

SSE Stream Endpoint Pattern

What is the correct Content-Type header for an SSE (Server-Sent Events) endpoint?

Lesson Recap: Real-Time Notification Feed

Notification feeds combine SSE subscription (useEffect with EventSource cleanup) with REST mutations (PATCH for mark-as-read). Data shape: {id, type, message, timestamp, read}. Derive unreadCount with filter, group by today/yesterday/older for display. Use global context or Zustand for cross-page toasts. Persist to localStorage for navigation resilience. SSE endpoint requires Content-Type: text/event-stream, Cache-Control: no-cache, and double-newline event delimiters.

Frequently asked questions

Is the “Building a Real-Time Notification Feed” lesson free?

Yes — the full text of “Building a Real-Time Notification Feed” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.

What will I learn in “Building a Real-Time Notification Feed”?

Combine SSE with React state to build a notification feed that updates in real time without user interaction. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start React Academy?

No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Building a Real-Time Notification Feed” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this React Academy lesson?

Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. SSE vs WebSockets vs Polling Comparison
  2. Consuming SSE Streams in React with EventSource
  3. Long Polling Pattern and Reconnection Logic
  4. Building a Real-Time Notification Feed
← Back to React Academy