How to make server-sent events work in React "custom hooks"?

75 Views Asked by At

I'm learning React. I'm working on a project where I acquire data from a server-sent events data stream initiated every time my local state deviceState = "started". I achieved doing the job and was pretty happy.

But the code was very redundant as I was doing the same for 3 different sources of data. So I thought I'd try to write my first custom hook and get the code cleaner.

I think I have been pretty cautious at providing the right arguments(especially deviceState as well as the url of the source) to my custom hooks and did not change the structure of my code to acquire the data and update the local state accordingly.

Yet, using the VS debugger, I can see that my program is never entering into the data streaming process since I included it into the custom hook : It tries once and does not detect any incoming event despite the provided url being correct and the server working smoothly

Would you suspect any obscure reason for that ?

If that helps, please find the code below :

import { useEffect, useState } from "react";

export function useSSEdatastream(url: string, deviceState: 'started' | 'stopped', dataSeriesName:string, nbDataOnXaxis: number = 300, samplingRate: number = 15) {

    const initialData: [number, number][] = Array.from({ length: nbDataOnXaxis }, () => [0, 0]);
    const [dataChunk, setDataChunk] = useState<[number, number][]>(initialData);
    const dataSeries = [
        {
          name: dataSeriesName,
          data: dataChunk
        }];


    useEffect(() => {
        if (deviceState === 'started') {
            let source_rawdata: EventSource | null = new EventSource(url);

            source_rawdata.onmessage = (event) => {
                try {
                    const line = JSON.parse(event.data.replace(/'/g, '"'))
                    for (let i = 0; i < line.length - 1; i++) {                // Reprendre le code ici pour intégrer les chunks de taille > 1
                        const data_line = [line[i].timestamp * 1000, line[i].value]
                        setDataChunk(prevData => [...prevData.slice(1), data_line] as [number, number][])
                    }
                } catch (error) {
                    console.error('Error processing event:', error);
                }
            };

            source_rawdata.onerror = (error) => {
                console.error('EventSource failed:', error);
                source_rawdata?.close();
                source_rawdata = null;

                // Reconnect after a delay (e.g., 2 seconds)
                setTimeout(() => {
                    source_rawdata = new EventSource(url);
                }, 2000);
            };

            return () => {
                source_rawdata?.close();
            };
        }
    }, [deviceState]);

    return {
        dataSeries, dataChunk
    }

}

I tried to move the code underlying the SSE into a custom hook to get my code cleaner and expected the data to be gathered the same way than when the code was outside the hook.

0

There are 0 best solutions below