useD4Metrics.ts 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. "use client";
  2. import { useCallback, useEffect, useMemo, useState } from "react";
  3. import { fetchD4Metrics, type D4MetricsQuery, type D4MetricsResponse } from "@/lib/d4Metrics";
  4. export interface UseD4MetricsOptions {
  5. enabled?: boolean;
  6. }
  7. export function useD4Metrics(query: D4MetricsQuery = {}, options: UseD4MetricsOptions = {}) {
  8. const enabled = options.enabled ?? true;
  9. const queryKey = useMemo(() => JSON.stringify(query), [query]);
  10. const [refreshIndex, setRefreshIndex] = useState(0);
  11. const requestKey = `${queryKey}:${refreshIndex}`;
  12. const [result, setResult] = useState<{
  13. key: string | null;
  14. data: D4MetricsResponse | null;
  15. error: string | null;
  16. }>({
  17. key: null,
  18. data: null,
  19. error: null,
  20. });
  21. const refetch = useCallback(() => {
  22. setRefreshIndex((current) => current + 1);
  23. }, []);
  24. useEffect(() => {
  25. if (!enabled) {
  26. return;
  27. }
  28. const abortController = new AbortController();
  29. const parsedQuery = JSON.parse(queryKey) as D4MetricsQuery;
  30. fetchD4Metrics(parsedQuery, abortController.signal)
  31. .then((response) => {
  32. setResult({
  33. key: requestKey,
  34. data: response,
  35. error: null,
  36. });
  37. })
  38. .catch((requestError: unknown) => {
  39. if (abortController.signal.aborted) {
  40. return;
  41. }
  42. setResult({
  43. key: requestKey,
  44. data: null,
  45. error: requestError instanceof Error ? requestError.message : "D4 指标请求失败",
  46. });
  47. });
  48. return () => {
  49. abortController.abort();
  50. };
  51. }, [enabled, queryKey, requestKey]);
  52. const isCurrentResult = result.key === requestKey;
  53. return {
  54. data: isCurrentResult ? result.data : null,
  55. error: isCurrentResult ? result.error : null,
  56. isLoading: enabled && !isCurrentResult,
  57. refetch,
  58. };
  59. }