Files
trade-visualizer/src/features/ticks/useTicks.ts

53 lines
1.4 KiB
TypeScript

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { DriftTick, fetchLatestTicks } from '../../lib/hasura';
import { useInterval } from '../../app/hooks/useInterval';
type Params = {
symbol: string;
source?: string;
limit: number;
pollMs: number;
};
type Result = {
ticks: DriftTick[];
latest: DriftTick | null;
loading: boolean;
error: string | null;
refresh: () => Promise<void>;
};
export function useTicks({ symbol, source, limit, pollMs }: Params): Result {
const [ticks, setTicks] = useState<DriftTick[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const inFlight = useRef(false);
const fetchOnce = useCallback(async () => {
if (inFlight.current) return;
inFlight.current = true;
setLoading(true);
try {
const next = await fetchLatestTicks(symbol, limit, source?.trim() ? source : undefined);
setTicks(next);
setError(null);
} catch (e: any) {
setError(String(e?.message || e));
} finally {
setLoading(false);
inFlight.current = false;
}
}, [symbol, limit, source]);
useEffect(() => {
void fetchOnce();
}, [fetchOnce]);
useInterval(() => void fetchOnce(), pollMs);
const latest = useMemo(() => (ticks.length ? ticks[ticks.length - 1] : null), [ticks]);
return { ticks, latest, loading, error, refresh: fetchOnce };
}