geo/frontend/lib/hooks/use-compare-data.ts

81 lines
2.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 竞品对比页面数据获取 Hook
*
* 封装品牌列表 + 对比数据的 SWR 请求,替代手动 useState + useEffect 模式。
* - 品牌列表mount 时自动获取
* - 对比数据:依赖 selectedBrandId为空时暂停请求
*/
import { useState, useCallback } from "react";
import { useApi } from "./use-api";
import type { SWRConfiguration } from "swr";
import type { BrandListResponse, BrandListItem, CompareResponse } from "@/types/brand";
export interface UseCompareDataReturn {
/** 品牌列表 */
brands: BrandListItem[];
/** 当前选中的品牌 ID */
selectedBrandId: string;
/** 设置选中的品牌 ID */
setSelectedBrandId: (id: string) => void;
/** 对比数据 */
compareData: CompareResponse | undefined;
/** 是否正在加载(品牌列表或对比数据任一加载中) */
isLoading: boolean;
/** 错误信息 */
error: Error | undefined;
/** 刷新品牌列表 */
refreshBrands: () => void;
/** 刷新对比数据 */
refreshCompare: () => void;
}
export interface UseCompareDataOptions {
/** 初始选中的品牌 ID */
initialBrandId?: string;
/** SWR 配置(用于测试时禁用重试等) */
swrOptions?: SWRConfiguration;
}
export function useCompareData(
options?: UseCompareDataOptions
): UseCompareDataReturn {
const initialBrandId = options?.initialBrandId;
const swrOptions = options?.swrOptions;
const [selectedBrandId, setSelectedBrandId] = useState<string>(initialBrandId ?? "");
// 品牌列表
const {
data: brandsResponse,
isLoading: brandsLoading,
error: brandsError,
refresh: refreshBrands,
} = useApi<BrandListResponse>("/api/v1/brands/", swrOptions);
const brands: BrandListItem[] = brandsResponse?.items ?? [];
// 对比数据 — 依赖 selectedBrandId为空时暂停
const compareUrl = selectedBrandId ? `/api/v1/brands/${selectedBrandId}/compare` : null;
const {
data: compareData,
isLoading: compareLoading,
error: compareError,
refresh: refreshCompare,
} = useApi<CompareResponse>(compareUrl, swrOptions);
const isLoading = brandsLoading || compareLoading;
const error = brandsError || compareError;
return {
brands,
selectedBrandId,
setSelectedBrandId,
compareData,
isLoading,
error,
refreshBrands,
refreshCompare,
};
}