76 lines
2.2 KiB
TypeScript
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 };
|
|
}
|