Files
lst_v3/frontend/src/hooks/socket.io.hook.ts

101 lines
2.2 KiB
TypeScript

import { useCallback, useEffect, useState } from "react";
import socket from "@/lib/socket.io";
type RoomUpdatePayload<T> = {
roomId: string;
payloads: T[];
};
type RoomErrorPayload = {
roomId?: string;
message?: string;
};
type UpdateMode = "append" | "replace";
export function useSocketRoom<T>(
roomId: string,
getKey?: (item: T) => string | number,
updateMode: UpdateMode = "append",
) {
const [data, setData] = useState<T[]>([]);
const [info, setInfo] = useState(
"No data yet — join the room to start receiving",
);
const clearRoom = useCallback(
(id?: string | number) => {
if (id !== undefined && getKey) {
setData((prev) => prev.filter((item) => getKey(item) !== id));
setInfo(`Removed item ${id}`);
return;
}
console.log("cleared data from the room");
setData([]);
setInfo("Room data cleared");
},
[getKey],
);
useEffect(() => {
function handleConnect() {
socket.emit("join-room", roomId);
setInfo(`Joined room: ${roomId}`);
}
function handleUpdate(payload: RoomUpdatePayload<T>) {
// protects against other room updates hitting this hook
if (payload.roomId !== roomId) return;
// resetting room data for rooms that just need updated data.
if (updateMode === "replace") {
setData(payload.payloads);
} else {
setData((prev) => [...payload.payloads, ...prev]);
}
setInfo("");
}
function handleError(err: RoomErrorPayload) {
if (err.roomId && err.roomId !== roomId) return;
setInfo(err.message ?? "Room error");
}
socket.on("connect", handleConnect);
socket.on("room-update", handleUpdate);
socket.on("room-error", handleError);
if (!socket.connected && socket.disconnected) {
socket.connect();
}
// If already connected, join immediately
if (socket.connected) {
socket.emit("join-room", roomId);
setInfo(`Joined room: ${roomId}`);
}
return () => {
socket.emit("leave-room", roomId);
socket.off("connect", handleConnect);
socket.off("room-update", handleUpdate);
socket.off("room-error", handleError);
};
}, [roomId, updateMode]);
return { data, info, clearRoom };
}
/*
const isDockDoorPage = location.pathname.startsWith("/dockdoor");
useSocketRoom(
dockId ? `dockdoor:${dockId}` : null,
isDockDoorPage,
);
*/