Effortless Real-Time Updates in React with Server-Sent Events: A Step-by-Step Guide Using Node.js and Express
In modern applications, real-time data is a common requirement. From live sports scores to chat notifications and system alerts, users expect to see data updates without refreshing the page. Traditionally, real-time updates involve various techniques: polling APIs at intervals, using WebSockets for two-way communication, or Server-Sent Events (SSE) for one-way server-to-client updates.
So, why choose Server-Sent Events? Here’s the catch: if you only need updates from the server to the client, adding a WebSocket can add unnecessary complexity, resource demands, and maintenance. SSE provides a lightweight and efficient solution, making it perfect for simpler real-time requirements.
In this guide, I’ll show you how to use SSE with a Node.js and Express server and a React frontend.
Why Server-Sent Events (SSE)?
When choosing between WebSockets and SSE, here are a few distinctions:
- WebSockets provide full-duplex communication, meaning both the server and client can send and receive messages.
- Server-Sent Events are one-way: the server can send updates to the client, but the client cannot respond via the same connection. This makes SSE ideal for use cases where you only need to push notifications from the server to the client without complex bidirectional communication.
Some advantages of SSE over WebSockets for simple real-time needs include:
- Simplicity: You don’t need to set up the same infrastructure or event handlers for both ends.
- Less Overhead: SSE is less resource-intensive since the connection is managed by the browser.
- Built-in Reconnection: If the connection drops, the browser automatically attempts to reconnect.
Setting Up Server-Sent Events with Node.js and Express
Let’s dive into setting up a basic SSE endpoint with Node.js and Express.
1. Install the necessary dependencies:
npm install express
2. Create an Express server with an SSE endpoint. We’ll use the endpoint /events
to send real-time updates from the server.
// server.js
const express = require('express');
const app = express();
const PORT = 3000;
app.get('/events', (req, res) => {
// Set headers to establish SSE connection
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// Send a message every 5 seconds for demonstration purposes
const intervalId = setInterval(() => {
const message = { data: 'Hello from the server!' };
res.write(`data: ${JSON.stringify(message)}\n\n`);
}, 5000);
// Close the connection when the client disconnects
req.on('close', () => {
clearInterval(intervalId);
res.end();
});
});
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
- Headers: The headers
Content-Type: text/event-stream
andCache-Control: no-cache
are essential for creating an SSE connection. - Data Format: The server sends messages as
data: <content>\n\n
. Here, we send JSON data, but it could be plain text.
3. Run the server:
node server.js
Your SSE server is now set up and running on http://localhost:3000/events
.
Setting Up the React Client to Listen for SSE
Now, let’s build the React client to listen for these events and update the UI in real-time.
1. Create a new React component called useSSE.js
to handle the SSE connection and return any messages.
import { useEffect, useState } from 'react';
function useSSE(url) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
const eventSource = new EventSource(url);
// Handle incoming data
eventSource.onmessage = (event) => {
const newData = JSON.parse(event.data);
setData(newData);
};
// Handle errors
eventSource.onerror = () => {
setError('Connection lost. Trying to reconnect...');
eventSource.close();
};
// Cleanup when component unmounts
return () => eventSource.close();
}, [url]);
return { data, error };
}
export default useSSE;
2. Use the hook in your main component. This will initialize the SSE connection to our server.
// App.js
import React from 'react';
import useSSE from './useSSE';
function App() {
const { data, error } = useSSE('http://localhost:3000/events');
return (
<div>
<h1>Server-Sent Events in React</h1>
{error && <p>{error}</p>}
{data ? <p>Message from server: {data.data}</p> : <p>Waiting for updates...</p>}
</div>
);
}
export default App;
Here, our React component will display the server’s messages in real-time. The useSSE
hook manages the EventSource
connection, and any incoming messages update the state and UI immediately.
3. Run your React app:
npm start
Benefits of SSE in Your React App
Using Server-Sent Events simplifies your app in several ways:
- Reduced Code Complexity: No need to handle both directions of communication, as is required with WebSockets.
- Less Infrastructure Overhead: You avoid the additional setup and ongoing resource demands of a WebSocket connection.
- Automatic Reconnection: If the connection is lost, the browser will automatically attempt to reconnect, making your app more resilient.
Conclusion
SSE is a powerful and lightweight option for real-time server-to-client updates, especially in cases where you don’t need full-duplex communication. Integrating SSE with a Node.js server and a React frontend is straightforward, requiring minimal setup and no extra libraries.
While WebSockets and long polling have their places in real-time applications, Server-Sent Events shine when you need a simple, efficient way to push server updates to the client. Try it in your next React project to keep your users informed in real time!
Reference Links
- EventSource Docs: Official MDN Web Docs for Event Source Javascript API
Find me on your favorite platform
- Github — Follow me on GitHub for further useful code snippets and open source repos.
- My Portfolio — Connect with me through my portfolio
- LinkedIn Profile — Connect with me on LinkedIn for further discussions and updates.
- Twitter (X) — Connect with me on Twitter (X) for useless tech tweets.