mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-01 16:24:48 +03:00
b9cbc0c1e8
List pages wrapped content in <Spin spinning={!fetched}> where 'fetched' only flipped true once data arrived. With staleTime: Infinity + retry: 1, a transient network error on first load left the query in a permanent error state and the spinner stuck forever.
Now 'fetched' also settles on query.isError, and a failed load shows a Result error card with a Refresh button that self-heals when the backend returns, mirroring the existing XrayPage pattern. Applied to clients, inbounds, groups, nodes, and the dashboard.
Fixes #4723
38 lines
1.2 KiB
TypeScript
38 lines
1.2 KiB
TypeScript
import { useQuery } from '@tanstack/react-query';
|
|
import { useMemo } from 'react';
|
|
|
|
import { HttpUtil } from '@/utils';
|
|
import { parseMsg } from '@/utils/zodValidate';
|
|
import { Status } from '@/models/status';
|
|
import { StatusSchema } from '@/schemas/status';
|
|
import { keys } from '@/api/queryKeys';
|
|
|
|
const POLL_INTERVAL_MS = 2000;
|
|
|
|
async function fetchStatus(): Promise<Status> {
|
|
const msg = await HttpUtil.get('/panel/api/server/status', undefined, { silent: true });
|
|
if (!msg?.success) throw new Error(msg?.msg || 'Failed to fetch status');
|
|
const validated = parseMsg(msg, StatusSchema, 'server/status');
|
|
return new Status(validated.obj);
|
|
}
|
|
|
|
export function useStatusQuery() {
|
|
const query = useQuery({
|
|
queryKey: keys.server.status(),
|
|
queryFn: fetchStatus,
|
|
refetchInterval: POLL_INTERVAL_MS,
|
|
refetchIntervalInBackground: false,
|
|
staleTime: 0,
|
|
});
|
|
|
|
const status = useMemo(() => query.data ?? new Status(), [query.data]);
|
|
const refresh = async () => { await query.refetch(); };
|
|
|
|
return {
|
|
status,
|
|
fetched: query.data !== undefined || query.isError,
|
|
fetchError: query.error ? (query.error as Error).message : '',
|
|
refresh,
|
|
};
|
|
}
|