85 lines
1.8 KiB
TypeScript
85 lines
1.8 KiB
TypeScript
'use client'
|
|
|
|
import React, { createContext, useContext, useRef, useState, ReactNode, useEffect } from 'react'
|
|
import { Map } from 'maplibre-gl';
|
|
import { gql, useSubscription } from '@apollo/client';
|
|
|
|
// 定义MapContext的类型
|
|
interface WSContextType {
|
|
wsStatus: WsStatus
|
|
setWsStatus: (status: WsStatus) => void
|
|
data: any
|
|
loading: boolean
|
|
error: any
|
|
restart: () => void
|
|
}
|
|
|
|
enum WsStatus {
|
|
CONNECTING = 'connecting',
|
|
CONNECTED = 'connected',
|
|
DISCONNECTED = 'disconnected'
|
|
}
|
|
|
|
// 创建Context
|
|
const WSContext = createContext<WSContextType | undefined>(undefined)
|
|
|
|
// Provider组件的Props类型
|
|
interface MapProviderProps {
|
|
children: ReactNode
|
|
}
|
|
|
|
const SUBSCRIPTION_QUERY = gql`
|
|
subscription {
|
|
statusUpdates {
|
|
id
|
|
message
|
|
status
|
|
timestamp
|
|
newestDt
|
|
}
|
|
}
|
|
`
|
|
|
|
|
|
// Provider组件
|
|
export function WSProvider({ children }: MapProviderProps) {
|
|
|
|
const [wsStatus, setWsStatus] = useState<WsStatus>(WsStatus.DISCONNECTED)
|
|
const { data, loading, error, restart } = useSubscription(SUBSCRIPTION_QUERY)
|
|
|
|
useEffect(() => {
|
|
if (loading) {
|
|
setWsStatus(WsStatus.CONNECTING)
|
|
} else if (error) {
|
|
setWsStatus(WsStatus.DISCONNECTED)
|
|
} else {
|
|
setWsStatus(WsStatus.CONNECTED)
|
|
}
|
|
}, [data])
|
|
|
|
const value: WSContextType = {
|
|
wsStatus,
|
|
setWsStatus,
|
|
data,
|
|
loading,
|
|
error,
|
|
restart
|
|
}
|
|
|
|
return (
|
|
<WSContext.Provider value={value}>
|
|
{children}
|
|
</WSContext.Provider>
|
|
)
|
|
}
|
|
|
|
// 自定义Hook用于使用MapContext
|
|
export function useWS() {
|
|
const context = useContext(WSContext)
|
|
|
|
if (context === undefined) {
|
|
throw new Error('useWS must be used within a WSProvider')
|
|
}
|
|
|
|
return context
|
|
} |