cosmo/frontend/src/hooks/useHistoricalData.ts

76 lines
2.2 KiB
TypeScript

/**
* Custom hook for fetching historical celestial data
*/
import { useState, useEffect, useRef } from 'react';
import { fetchCelestialPositions } from '../utils/api';
import type { CelestialBody } from '../types';
export function useHistoricalData(selectedDate: Date | null) {
const [bodies, setBodies] = useState<CelestialBody[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
// 使用 ref 跟踪上次请求的时间,避免重复请求
const lastFetchedDateRef = useRef<string | null>(null);
useEffect(() => {
if (!selectedDate) {
return;
}
// Track if this effect instance is active
let isActive = true;
// 创建午夜时间戳
const targetDate = new Date(selectedDate);
targetDate.setUTCHours(0, 0, 0, 0);
const dateKey = targetDate.toISOString();
// 如果是同一个时间点,不重复请求
if (lastFetchedDateRef.current === dateKey) {
return;
}
const loadHistoricalData = async () => {
try {
setLoading(true);
setError(null);
console.log(`[useHistoricalData] Fetching data for ${dateKey}`);
// Set start and end to the same time to get a single snapshot
const data = await fetchCelestialPositions(
targetDate.toISOString(),
targetDate.toISOString(), // Same as start - single point in time
'1d'
);
// Only update state if this effect is still active
if (isActive) {
setBodies(data.bodies);
lastFetchedDateRef.current = dateKey; // 记录已请求的时间
console.log(`[useHistoricalData] Loaded ${data.bodies.length} bodies`);
setLoading(false);
} else {
console.log(`[useHistoricalData] Ignored stale data for ${dateKey}`);
}
} catch (err) {
if (isActive) {
console.error('Failed to fetch historical data:', err);
setError(err instanceof Error ? err.message : 'Unknown error');
setLoading(false);
}
}
};
loadHistoricalData();
// Cleanup function
return () => {
isActive = false;
};
}, [selectedDate]);
return { bodies, loading, error };
}