diff --git a/bun.lockb b/bun.lockb index a5dc9ca..75b1bb1 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/projects/website/package.json b/projects/website/package.json index 7fc0077..fc3fb03 100644 --- a/projects/website/package.json +++ b/projects/website/package.json @@ -44,6 +44,7 @@ "react-countup": "^6.5.3", "react-dom": "^19.0.0-rc-1460d67c-20241003", "react-hook-form": "^7.53.0", + "react-use-websocket": "^4.9.0", "tailwind-merge": "^2.5.2", "tailwindcss-animate": "^1.0.7", "zod": "^3.23.8" diff --git a/projects/website/src/components/score/score-feed/score-feed.tsx b/projects/website/src/components/score/score-feed/score-feed.tsx index ef07ab2..16f7278 100644 --- a/projects/website/src/components/score/score-feed/score-feed.tsx +++ b/projects/website/src/components/score/score-feed/score-feed.tsx @@ -5,18 +5,18 @@ import ScoreSaberPlayerScoreToken from "@ssr/common/types/token/scoresaber/score import Score from "@/components/score/score"; import { parseDate } from "@ssr/common/utils/time-utils"; import Link from "next/link"; -import { useWebSocket } from "@/hooks/use-websocket"; +import useWebSocket, { ReadyState } from "react-use-websocket"; import { ScoreSaberWebsocketMessageToken } from "@ssr/common/types/token/scoresaber/websocket/scoresaber-websocket-message"; export default function ScoreFeed() { - const { connected, message } = useWebSocket("wss://scoresaber.com/ws"); + const { readyState, lastJsonMessage } = useWebSocket("wss://scoresaber.com/ws"); const [scores, setScores] = useState([]); useEffect(() => { - if (!message) { + if (!lastJsonMessage) { return; } - const { commandName, commandData } = message; + const { commandName, commandData } = lastJsonMessage; if (commandName !== "score") { return; } @@ -30,9 +30,9 @@ export default function ScoreFeed() { // Newest to oldest return newScores.sort((a, b) => parseDate(b.score.timeSet).getTime() - parseDate(a.score.timeSet).getTime()); }); - }, [message]); + }, [lastJsonMessage]); - if (!connected) { + if (readyState == ReadyState.CONNECTING) { return

Not Connected to the ScoreSaber Websocket :(

; } diff --git a/projects/website/src/hooks/use-websocket.ts b/projects/website/src/hooks/use-websocket.ts deleted file mode 100644 index db10c8a..0000000 --- a/projects/website/src/hooks/use-websocket.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { useEffect, useRef, useState } from "react"; - -/** - * Generic WebSocket hook for connecting and handling WebSocket messages of type T. - * - * @param url - The WebSocket server URL. - * @param reconnectDelay - Optional delay (in milliseconds) before attempting to reconnect (default is 5000ms). - */ -export const useWebSocket = (url: string, reconnectDelay: number = 5000) => { - const [connected, setConnected] = useState(false); - const [message, setMessage] = useState(null); // Store the incoming message of type T - const socketRef = useRef(null); - const reconnectTimeoutRef = useRef(null); - const [mounted, setMounted] = useState(false); - - useEffect(() => { - setMounted(true); - }, []); - - useEffect(() => { - if (!mounted) { - return; - } - - const connectWebSocket = () => { - socketRef.current = new WebSocket(url); - - socketRef.current.onopen = () => { - setConnected(true); - }; - - socketRef.current.onmessage = event => { - try { - // Handle incoming messages and store them in state as type T - const messageData: T = JSON.parse(event.data); - setMessage(messageData); - } catch (error) { - console.error("Error parsing WebSocket message:", error); - } - }; - - socketRef.current.onclose = () => { - setConnected(false); - attemptReconnect(); - }; - - socketRef.current.onerror = () => { - socketRef.current?.close(); // Close the socket on error - }; - }; - - const attemptReconnect = () => { - // Clear any existing timeouts to avoid multiple reconnection attempts - if (reconnectTimeoutRef.current) { - clearTimeout(reconnectTimeoutRef.current); - } - // Try reconnecting after the specified delay - reconnectTimeoutRef.current = setTimeout(() => { - connectWebSocket(); - }, reconnectDelay); - }; - - // Initialize WebSocket connection - connectWebSocket(); - - // Cleanup function when component unmounts - return () => { - if (socketRef.current) { - socketRef.current.close(); - socketRef.current = null; - } - if (reconnectTimeoutRef.current) { - clearTimeout(reconnectTimeoutRef.current); - } - }; - }, [mounted, url, reconnectDelay]); - - return { connected, message }; -};