UNPKG

@orchard9ai/error-handling

Version:

Federated error handling package with go-core-http-toolkit format support and logging integration

109 lines (91 loc) 2.86 kB
import * as React from 'react'; import { HttpClient, type HttpClientConfig } from '../handlers/HttpClient.js'; /** * React hook for HTTP client with automatic cleanup */ export function useHttpClient(config?: HttpClientConfig): HttpClient { const abortControllers = React.useRef<Set<AbortController>>(new Set()); // Create client once const client = React.useMemo(() => { const httpClient = new HttpClient(config); // Wrap request method to track abort controllers const originalRequest = httpClient.request.bind(httpClient); httpClient.request = async function(endpoint, requestConfig = {}) { const controller = new AbortController(); abortControllers.current.add(controller); try { const result = await originalRequest(endpoint, { ...requestConfig, signal: controller.signal }); abortControllers.current.delete(controller); return result; } catch (error) { abortControllers.current.delete(controller); throw error; } }; return httpClient; }, []); // Only create once // Cleanup on unmount React.useEffect(() => { return () => { // Abort all pending requests abortControllers.current.forEach(controller => { controller.abort(); }); abortControllers.current.clear(); }; }, []); return client; } /** * Hook for making HTTP requests with automatic cleanup */ export function useHttpRequest<T = any>( client: HttpClient, endpoint: string, config?: Parameters<HttpClient['request']>[1] ) { const [state, setState] = React.useState<{ data: T | null; loading: boolean; error: Error | null; }>({ data: null, loading: false, error: null }); const abortControllerRef = React.useRef<AbortController | null>(null); const execute = React.useCallback(async () => { // Abort previous request if (abortControllerRef.current) { abortControllerRef.current.abort(); } const controller = new AbortController(); abortControllerRef.current = controller; setState({ data: null, loading: true, error: null }); try { const response = await client.request<T>(endpoint, { ...config, signal: controller.signal }); if (!controller.signal.aborted) { setState({ data: response.data, loading: false, error: null }); } } catch (error) { if (!controller.signal.aborted) { setState({ data: null, loading: false, error: error as Error }); } } }, [client, endpoint, config]); // Cleanup on unmount React.useEffect(() => { return () => { if (abortControllerRef.current) { abortControllerRef.current.abort(); } }; }, []); return { ...state, execute }; }