🪟 Windows TippsModify Windows Support Phone Number with PowerShell(03.09.2026 um 00:00 Uhr)
🔧 AI Nachrichten Podcast: ChatGPT schwatzt Nutzern in Deutschland jetzt Werbung auf(28.08.2026 um 08:46 Uhr)
🪟 Windows TippsMicrosoft bringt Emoji 17.0 auf Windows 11(31.08.2026 um 08:16 Uhr)
🪟 Windows TippsModify Windows Support Phone Number with PowerShell(03.09.2026 um 00:00 Uhr)
🔧 AI Nachrichten Podcast: ChatGPT schwatzt Nutzern in Deutschland jetzt Werbung auf(28.08.2026 um 08:46 Uhr)
🪟 Windows TippsMicrosoft bringt Emoji 17.0 auf Windows 11(31.08.2026 um 08:16 Uhr)

🔧 Programmierung 🕛 vor 1 Jahr 12 Min Lesezeit
0

SSE, WebSockets, or Polling? Build a Real-Time Stock App with React and Hono

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

Have you ever tried building a dashboard that updates in real time? Or maybe wondered how sites like ChatGPT stream response data to the page? Or how Figma makes collaborative editing seem so seamless?



Today we'll try to answer these questions by looking at some methods to stream real-time data and build our own small real-time stock market feed app in to display randomly generated data.






Short Polling



The first method we'll take a look at is short polling, which is a technique for somewhat real-time communication.

It involves the client querying the server at regular intervals, usually a few seconds between requests, then updating the data on the client if necessary.



While this isn't exactly "real time", it can be good enough for many scenarios where updates don't need to be immediate or are infrequent, like checking for updates in an email inbox or a weather app where updates can occur every few minutes.



Short polling offers a few advantages:




  • It's pretty simple to implement

  • It doesn't require a persistent connection

  • It works with any HTTP client or browser



So let's take a look at the code:



Server




CODE
const updateStockPrices = () => {
stocks = stocks.map((stock) => ({
...stock,
// Randomly increment or decrement the stock price
price: Math.abs(stock.price + getStockPriceChange()),
}));
};

setInterval(updateStockPrices, 5 * 1000);

app.get("/stocks", (c) => {
return c.json({ stocks });
});






Client




CODE
const { data: stocksData } = useQuery({
queryKey: ["stocks"],
queryFn: async () =>
fetch("http://localhost:3000/stocks").then((response) =>
response.json() as Promise<{ stocks: Stock[] }>
),
refetchInterval: 5 * 1000,
});






For the server, I simulated frequent data updates by updating stock prices randomly. For simplicity's sake I set an interval to update the data every 5 seconds (even though data updates in real-time apps can be much more unpredictable). As for the client, I used



While simple, this solution has a few issues:




  • First of all, in this type of app the data can change quite frequently. This means that the interval might be too low and the client might "miss" some data on the server. While we can always lower the fetching interval, this can come at the cost of load to our server and additional network traffic on the client.

  • Many times, we might be querying the server when the data hasn't really changed, creating even more unnecessary load on the server.

  • While fetching the data often lowers the margin of error we might encounter on the client, we still don't get a true real time experience.






WebSockets



The next method we'll look at is WebSockets. Using WebSockets allows a persistent, bi-directional (two-way) communication channel between a client and a server. Unlike traditional HTTP, which follows a request-response model, WebSockets keep the connection open, so both the client and server can send messages to each other at any time.



WebSocket connections can be created over HTTP (ws) or HTTPS (wss), with wss ensuring the communication is encrypted and secure.



How it works





  1. Handshake:
    The connection starts with an HTTP handshake, after which the protocol ) or live updating dashboards (like the one we're trying to build!).



    WebSockets also offer a few advantages:





    • They offer true real-time communication, unlike short polling, making them ideal for high-frequency low latency updates.


    • Network efficiency: In that the connection between client and server remains open, reducing repeated handshakes and network overhead.


    • Bi-directional updates: Both client and server can message each other.



    Now let's implement them in our app:



    Server




    CODE
    const updateStockPrices = () => {
    stocks = stocks.map((stock) => ({
    ...stock,
    price: stock.price + getStockPriceChange(),
    time: Date.now(),
    }));

    eventEmitter.emit("stocksUpdated");
    scheduleNextUpdate();
    };

    app.get(
    "/stocks-ws",
    upgradeWebSocket((c) => {
    let sendEventsToClient = () => {};

    return {
    onOpen(_, ws) {
    sendEventsToClient = () => {
    ws.send(JSON.stringify({ stocks }));
    };

    eventEmitter.on("stocksUpdated", sendEventsToClient);

    ws.send(JSON.stringify({ stocks }));
    },
    onClose: () => {
    eventEmitter.off("stocksUpdated", sendEventsToClient);
    },
    };
    }),
    );






    Client

    // useWebsocket.ts




    CODE
    import { useEffect, useState } from 'react';

    const sockets = new Map<string, { ws: WebSocket; refCount: number }>();

    export function useWebsocket<T>(url: string, valueParser: (value: string) => T = JSON.parse) {
    const [isReady, setIsReady] = useState(false);
    const [value, setValue] = useState<T | null>(null);

    useEffect(() => {
    if (!sockets.has(url)) {
    const ws = new WebSocket(url);
    sockets.set(url, { ws, refCount: 0 });

    ws.onopen = () => setIsReady(true);
    ws.onmessage = event => setValue(valueParser(event.data));
    ws.onclose = () => {
    sockets.delete(url);
    };
    }

    const socket = sockets.get(url);

    if (!socket) return;

    socket.refCount += 1;

    return () => {
    socket.refCount -= 1;

    // Close the WebSocket if no more references exist
    if (socket.refCount === 0 && socket.ws.OPEN) {
    socket.ws.close();
    sockets.delete(url);
    }
    };
    }, [url]);

    const send = (data: string | ArrayBuffer | SharedArrayBuffer | Blob | ArrayBufferView) => {
    const socket = sockets.get(url);
    if (socket && socket.ws.readyState === WebSocket.OPEN) {
    socket.ws.send(data);
    }
    };

    return { isReady, value, send };
    }







    // App.tsx




    CODE
    const { isReady, value: stocksData } = useWebsocket<{ stocks: Stock[] }>('ws://localhost:3000/stocks-ws');

    if (!isReady) return;

    // render logic






    For the server I used to update my endpoint when the data changed. For the client I created my own custom hook, which used the



    It's also worth noting that WebSockets can also integrate into your app's existing TanStack Query setup by sending messages of updates and not data, while TanStack Query handles cache and data revalidation, as can be seen in for a relatively lightweight react implementation or on running WebSockets over HTTP/2, it lacks wide support with many client libraries.


  2. Resource consumption: WebSocket connections remain open for their duration, consuming server resources such as memory and CPU. High numbers of concurrent connections can be intensive on server resources.


  3. Security risks: WebSockets bypass many standard HTTP security mechanisms like CORS or CSRF protections, which puts them at risk of .



    How it works




    1. The client initiates an HTTP request, with the Accept: text/event-stream header.

    2. The server responds with an HTTP 200 status and headers that define the connection is an SSE stream, like Content-Type: text/event-stream.

    3. The server then sends data over the open connection to the client, which processes the events using the EventSource API.



    SSE can be great in scenarios where the server needs to constantly stream real-time data to the client, such as ChatGPT's responses (which use SSE to deliver parts of the response in real time), live notifications (like for updating scores in sports apps), or live-updating dashboards.



    So what advantages does SSE have over WebSockets?




    • Simplicity: SSE can be much simpler than WebSockets, as things like client reconnection are handled automatically by the EventSource API, with no need for additional code or libraries.


    • Lightweight: SSE is designed for one-way communication (which might be just what we need in our app!). It doesn't require the overhead of managing bidirectional communication, which in turn can lead to lower resource usage.


    • HTTP/2 compatible: SSE leverages HTTP/2’s multiplexing, allowing multiple streams over a single connection and avoiding the browser’s concurrent connection limits.


    • Security: SSE integrates with HTTP features like CORS, and works more reliably with firewalls, load balancers, and HTTP security tools compared to WebSockets.




    With all that said, let's get to coding!



    Server




    CODE
    app.get("/stocks-sse", async (c) => {
    return streamSSE(c, async (stream) => {
    const sendEventToClient = async () => {
    await stream.writeSSE({ data: JSON.stringify({ stocks }) });
    };

    eventEmitter.on("stocksUpdated", sendEventToClient);

    stream.writeSSE({ data: JSON.stringify({ stocks }) });

    stream.onAbort(() => {
    eventEmitter.off("message", sendEventToClient);
    });

    while (true) {
    await stream.sleep(200);
    }
    });
    });







    Client

    // useSSE.ts




    CODE
    import { useEffect, useState } from 'react';

    const eventSources = new Map<string, { es: EventSource; refCount: number }>();

    export function useSSE<T>(url: string, valueParser: (value: string) => T = JSON.parse) {
    const [isConnected, setIsConnected] = useState(false);
    const [value, setValue] = useState<T | null>(null);
    const [error, setError] = useState<Event | null>(null);

    useEffect(() => {
    if (!eventSources.has(url)) {
    const es = new EventSource(url);
    eventSources.set(url, { es, refCount: 0 });

    es.onopen = () => setIsConnected(true);
    es.onmessage = event => setValue(valueParser(event.data));
    es.onerror = err => {
    setError(err);
    setIsConnected(false);

    // Optionally close the connection on certain errors
    if (es.readyState === EventSource.CLOSED) {
    eventSources.delete(url);
    }
    };
    }

    const eventSource = eventSources.get(url);

    if (!eventSource) return;

    eventSource.refCount += 1;

    return () => {
    eventSource.refCount -= 1;

    // Close the EventSource if no more references exist
    if (eventSource.refCount === 0) {
    eventSource.es.close();
    eventSources.delete(url);
    }
    };
    }, [url, valueParser]);

    return { isConnected, value, error };
    }







    // App.tsx




    CODE
     const {isConnected, value: stocksData} = useSSE<{stocks: Stock[]}>("http://localhost:3000/stocks-sse");

    if (!isConnected) return;

    // render logic






    Our server logic is pretty simple thanks to Hono's built in






    Are there other methods?



    While for this example I feel the methods I covered were the most appropriate, there are other real-time options you can implement in your app.




    • If you're looking for streaming between backend microservices, (offer both Websocket and SSE based implementations) and .






    Conclusion



    We've looked at 3 different methods for real-time updates, all of which have their own unique advantages. For our app, I would say that SSE is probably what I would go for thanks to it providing better real-time updates than short polling and being simpler and more lightweight than WebSockets. That being said, different requirements pose different challenges and there isn't a perfect solution. It's always best to assess the functionality we want to provide and try to find the method that would provide the best user experience and be as simple and maintainable as possible.




    • If we want to follow a long process that runs on the server in our client, or maybe have notifications that don't need to pop up immediately, I would recommend short polling for its simplicity and for not requiring diving into additional APIs.


    • In case we do want an immediate response on the client, and only require for the client to receive updates from the server (for things like live updates or real-time notifications), I would recommend SSE.


    • If we want the bi-directional communication and for our client to be able to send messages to the server, for things like chat apps or collaborative editing, I would recommend WebSockets, and perhaps pairing it with one of the libraries mentioned above.




    I hope this article taught you a thing or two about real-time data and how to handle it in your app. If you’ve tried other methods or have ideas from your own projects, I’d love to hear about them in the comments!



    You can find the complete code for the project built in this article in . Happy coding!

    Vollständiger Original-Bericht
    Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
    ↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Modify Windows Support Phone Number with PowerShell
1 Quelle
Die Zukunft des Einkaufens: Warum wir ein neues Kapitel aufschlagen (und wie du es mitschreiben kannst)
1 Quelle
ZDE Podcast 251: Wie sieht digitales Instore Marketing 2026 aus, Amit Chatterjee?
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten SSE, WebSockets, or Polling? Build a Real-Time Stock App with React and Hono

Thematisch verwandte Begriffe: WebSockets, Polling, Build, RealTime · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...