- Add #/routing-table with one-second polling and route filters - Separate auto-connect targets from local external endpoints - Remove the obsolete interfaces navigation module BREAKING CHANGE: #/interfaces is removed.
48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
import type { RoutingTableItem } from '@/types/api'
|
|
|
|
const POLL_INTERVAL_MS = 1000
|
|
|
|
interface UseRoutingTableResult {
|
|
routingTable: RoutingTableItem[]
|
|
isLoading: boolean
|
|
error: string | null
|
|
refresh: () => void
|
|
}
|
|
|
|
export function useRoutingTable(): UseRoutingTableResult {
|
|
const [routingTable, setRoutingTable] = useState<RoutingTableItem[]>([])
|
|
const [isLoading, setIsLoading] = useState(true)
|
|
const [error, setError] = useState<string | null>(null)
|
|
const mountedRef = useRef(true)
|
|
|
|
const fetchRoutingTable = useCallback(async () => {
|
|
try {
|
|
const response = await fetch('/api/routing-table')
|
|
if (!response.ok) throw new Error(`路由接口异常 (${response.status})`)
|
|
const payload: unknown = await response.json()
|
|
if (!Array.isArray(payload)) throw new Error('路由接口返回格式异常')
|
|
if (!mountedRef.current) return
|
|
setRoutingTable(payload as RoutingTableItem[])
|
|
setError(null)
|
|
} catch (err: unknown) {
|
|
if (mountedRef.current) setError(err instanceof Error ? err.message : String(err))
|
|
} finally {
|
|
if (mountedRef.current) setIsLoading(false)
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
mountedRef.current = true
|
|
void fetchRoutingTable()
|
|
const timer = window.setInterval(() => void fetchRoutingTable(), POLL_INTERVAL_MS)
|
|
return () => {
|
|
mountedRef.current = false
|
|
window.clearInterval(timer)
|
|
}
|
|
}, [fetchRoutingTable])
|
|
|
|
const refresh = useCallback(() => void fetchRoutingTable(), [fetchRoutingTable])
|
|
return { routingTable, isLoading, error, refresh }
|
|
}
|