diff --git a/src/components/ServerDetailChart.tsx b/src/components/ServerDetailChart.tsx index 8fbd478..a366f2c 100644 --- a/src/components/ServerDetailChart.tsx +++ b/src/components/ServerDetailChart.tsx @@ -6,7 +6,6 @@ import { formatNezhaInfo, formatRelativeTime } from "@/lib/utils"; import { NezhaAPI, NezhaAPIResponse } from "@/types/nezha-api"; import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; -import useWebSocket from "react-use-websocket"; import { Area, AreaChart, @@ -18,6 +17,7 @@ import { } from "recharts"; import { ServerDetailChartLoading } from "./loading/ServerDetailLoading"; import AnimatedCircularProgressBar from "./ui/animated-circular-progress-bar"; +import { useWebSocketContext } from "@/hooks/use-websocket-context"; type cpuChartData = { timeStamp: string; @@ -54,16 +54,11 @@ type connectChartData = { export default function ServerDetailChart() { const { id } = useParams(); - const { lastMessage, readyState } = useWebSocket("/api/v1/ws/server", { - shouldReconnect: () => true, - reconnectInterval: 3000, - }); + const { lastMessage, readyState } = useWebSocketContext(); // 检查连接状态 if (readyState !== 1) { - return ( - - ); + return ; } // 解析消息 diff --git a/src/components/ServerDetailOverview.tsx b/src/components/ServerDetailOverview.tsx index d4feb6c..d4f0818 100644 --- a/src/components/ServerDetailOverview.tsx +++ b/src/components/ServerDetailOverview.tsx @@ -3,24 +3,19 @@ import { ServerDetailLoading } from "@/components/loading/ServerDetailLoading"; import ServerFlag from "@/components/ServerFlag"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent } from "@/components/ui/card"; +import { useWebSocketContext } from "@/hooks/use-websocket-context"; import { cn, formatBytes, formatNezhaInfo } from "@/lib/utils"; import { NezhaAPIResponse } from "@/types/nezha-api"; import { useNavigate, useParams } from "react-router-dom"; -import useWebSocket from "react-use-websocket"; export default function ServerDetailOverview() { const navigate = useNavigate(); const { id } = useParams(); - const { lastMessage, readyState } = useWebSocket("/api/v1/ws/server", { - shouldReconnect: () => true, - reconnectInterval: 3000, - }); + const { lastMessage, readyState } = useWebSocketContext(); // 检查连接状态 if (readyState !== 1) { - return ( - - ); + return ; } // 解析消息 diff --git a/src/context/websocket-context.ts b/src/context/websocket-context.ts new file mode 100644 index 0000000..28badc5 --- /dev/null +++ b/src/context/websocket-context.ts @@ -0,0 +1,11 @@ +import { createContext } from "react"; + +export interface WebSocketContextType { + sendMessage: (message: string) => void; + lastMessage: MessageEvent | null; + readyState: number; +} + +export const WebSocketContext = createContext( + undefined, +); diff --git a/src/context/websocket-provider.tsx b/src/context/websocket-provider.tsx new file mode 100644 index 0000000..3ae59cd --- /dev/null +++ b/src/context/websocket-provider.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import { + WebSocketContext, + type WebSocketContextType, +} from "./websocket-context"; +import useWebSocket from "react-use-websocket"; + +interface WebSocketProviderProps { + url: string; + children: React.ReactNode; +} + +export const WebSocketProvider: React.FC = ({ + url, + children, +}) => { + const { sendMessage, lastMessage, readyState } = useWebSocket(url, { + reconnectAttempts: 10, + reconnectInterval: 3000, + shouldReconnect: () => true, + }); + + const contextValue: WebSocketContextType = { + sendMessage, + lastMessage, + readyState, + }; + + return ( + + {children} + + ); +}; diff --git a/src/hooks/use-websocket-context.ts b/src/hooks/use-websocket-context.ts new file mode 100644 index 0000000..37d707f --- /dev/null +++ b/src/hooks/use-websocket-context.ts @@ -0,0 +1,12 @@ +import { useContext } from "react"; +import { WebSocketContext } from "../context/websocket-context"; + +export const useWebSocketContext = () => { + const context = useContext(WebSocketContext); + if (context === undefined) { + throw new Error( + "useWebSocketContext must be used within a WebSocketProvider", + ); + } + return context; +}; diff --git a/src/main.tsx b/src/main.tsx index 3535ac8..0adcda8 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -7,6 +7,7 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { Toaster } from "sonner"; import { MotionProvider } from "./components/motion/motion-provider"; +import { WebSocketProvider } from "./context/websocket-provider"; const queryClient = new QueryClient(); @@ -15,19 +16,21 @@ ReactDOM.createRoot(document.getElementById("root")!).render( - - - + + + + + diff --git a/src/pages/Server.tsx b/src/pages/Server.tsx index c82c927..c76bc4b 100644 --- a/src/pages/Server.tsx +++ b/src/pages/Server.tsx @@ -1,4 +1,3 @@ -import useWebSocket from "react-use-websocket"; import { NezhaAPIResponse } from "@/types/nezha-api"; import ServerCard from "@/components/ServerCard"; import { formatNezhaInfo } from "@/lib/utils"; @@ -9,16 +8,14 @@ import { useQuery } from "@tanstack/react-query"; import { fetchServerGroup } from "@/lib/nezha-api"; import GroupSwitch from "@/components/GroupSwitch"; import { ServerGroup } from "@/types/nezha-api"; +import { useWebSocketContext } from "@/hooks/use-websocket-context"; export default function Servers() { const { data: groupData } = useQuery({ queryKey: ["server-group"], queryFn: () => fetchServerGroup(), }); - const { lastMessage, readyState } = useWebSocket("/api/v1/ws/server", { - shouldReconnect: () => true, - reconnectInterval: 3000, - }); + const { lastMessage, readyState } = useWebSocketContext(); // 添加分组状态 const [currentGroup, setCurrentGroup] = useState("All");