UNPKG

@cardql/react

Version:

CardQL SDK for React web applications with hooks and context providers

113 lines (97 loc) 2.52 kB
import { useState, useEffect, useCallback, useRef } from "react"; import { useCardQLClient } from "../context"; export interface UseQueryOptions { enabled?: boolean; refetchOnMount?: boolean; refetchInterval?: number; onSuccess?: (data: any) => void; onError?: (error: any) => void; } export interface UseQueryResult<T> { data: T | undefined; loading: boolean; error: any; refetch: () => Promise<void>; refresh: () => Promise<void>; } /** * Hook for executing GraphQL queries with CardQL */ export function useQuery<T = any>( query: string, variables?: any, options: UseQueryOptions = {} ): UseQueryResult<T> { const cardql = useCardQLClient(); const [data, setData] = useState<T | undefined>(undefined); const [loading, setLoading] = useState(true); const [error, setError] = useState<any>(null); const { enabled = true, refetchOnMount = true, refetchInterval, onSuccess, onError, } = options; const intervalRef = useRef<number>(); const mountedRef = useRef(true); const fetchData = useCallback(async () => { if (!enabled) return; setLoading(true); setError(null); try { const result = await cardql.client.requestWithRetry<T>(query, variables); if (mountedRef.current) { setData(result); setLoading(false); onSuccess?.(result); } } catch (err) { if (mountedRef.current) { setError(err); setLoading(false); onError?.(err); } } }, [cardql, query, variables, enabled, onSuccess, onError]); const refetch = useCallback(async () => { await fetchData(); }, [fetchData]); const refresh = useCallback(async () => { setData(undefined); await fetchData(); }, [fetchData]); // Initial fetch useEffect(() => { if (enabled && refetchOnMount) { fetchData(); } }, [enabled, refetchOnMount, fetchData]); // Set up refetch interval useEffect(() => { if (refetchInterval && enabled) { intervalRef.current = setInterval(fetchData, refetchInterval); return () => { if (intervalRef.current) { clearInterval(intervalRef.current); } }; } }, [refetchInterval, enabled, fetchData]); // Cleanup on unmount useEffect(() => { return () => { mountedRef.current = false; if (intervalRef.current) { clearInterval(intervalRef.current); } }; }, []); return { data, loading, error, refetch, refresh, }; }