UIKit/lib/hooks/useSSESubscription.ts

51 lines
1.7 KiB
TypeScript
Raw Normal View History

2023-07-10 17:48:09 +00:00
import { useEffect, useLayoutEffect, useRef } from "react";
2023-06-06 10:02:17 +00:00
import ReconnectingEventSource from "reconnecting-eventsource";
import { devlog } from "../utils";
export function useSSESubscription<T>({ enabled = true, url, onNewData, onDisconnect, marker = "" }: {
enabled?: boolean;
url: string;
onNewData: (data: T[]) => void;
2023-08-28 14:30:43 +00:00
onDisconnect?: () => void;
2023-06-06 10:02:17 +00:00
marker?: string;
}) {
2023-07-10 17:48:09 +00:00
const onNewDataRef = useRef(onNewData);
const onDisconnectRef = useRef(onDisconnect);
useLayoutEffect(() => {
onNewDataRef.current = onNewData;
onDisconnectRef.current = onDisconnect;
}, [onNewData, onDisconnect]);
2023-06-06 10:02:17 +00:00
useEffect(() => {
if (!enabled) return;
const eventSource = new ReconnectingEventSource(url);
eventSource.addEventListener("open", () => devlog(`EventSource connected with ${url}`));
eventSource.addEventListener("close", () => devlog(`EventSource closed with ${url}`));
eventSource.addEventListener("message", event => {
try {
console.log("EVENT")
console.log(event)
if (event.data !== '{"event": "ping"}') {
const newData = JSON.parse(event.data) as T;
devlog(`new SSE: ${marker}`, newData);
onNewDataRef.current([newData]);
}
2023-06-06 10:02:17 +00:00
} catch (error) {
devlog(`SSE parsing error: ${marker}`, event.data, error);
}
});
eventSource.addEventListener("error", event => {
devlog("SSE Error:", event);
});
return () => {
eventSource.close();
2023-08-28 14:30:43 +00:00
onDisconnectRef.current?.();
2023-06-06 10:02:17 +00:00
};
2023-07-10 17:48:09 +00:00
}, [enabled, marker, url]);
2023-08-28 14:30:43 +00:00
}