diff --git a/apps/mobile/src/contexts/StatisticsContext.tsx b/apps/mobile/src/contexts/StatisticsContext.tsx index f2502a2..ea82163 100644 --- a/apps/mobile/src/contexts/StatisticsContext.tsx +++ b/apps/mobile/src/contexts/StatisticsContext.tsx @@ -4,6 +4,7 @@ import React, { useState, useCallback, useEffect, + useRef, } from "react"; import { useUser, useAuth } from "@clerk/clerk-expo"; import { getUserStatistics } from "../api/statistics"; @@ -36,6 +37,9 @@ export function StatisticsProvider({ const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [lastFetchTime, setLastFetchTime] = useState(0); + const statisticsRef = useRef(null); + const lastFetchTimeRef = useRef(0); + const fetchInProgressRef = useRef(false); // Cache statistics for 30 seconds to avoid duplicate calls const CACHE_DURATION = 30000; // 30 seconds @@ -43,48 +47,49 @@ export function StatisticsProvider({ const refetchStatistics = useCallback(async () => { if (!user?.id) return; + if (fetchInProgressRef.current) { + return; + } + // Check if we have recent cached data const now = Date.now(); - if (statistics && now - lastFetchTime < CACHE_DURATION) { - log.debug("Using cached statistics", { - age: now - lastFetchTime, - cacheRemaining: CACHE_DURATION - (now - lastFetchTime), - }); + if ( + statisticsRef.current && + now - lastFetchTimeRef.current < CACHE_DURATION + ) { return; } try { + fetchInProgressRef.current = true; setLoading(true); setError(null); - log.debug("Fetching fresh statistics", { userId: user.id }); const token = await getToken(); const stats = await getUserStatistics(user.id, token); setStatistics(stats); + statisticsRef.current = stats; setLastFetchTime(now); - log.debug("Statistics fetched and cached", { - userId: user.id, - hasWeeklyTrend: !!stats.weeklyTrend, - weeklyTrendLength: stats.weeklyTrend?.length || 0, - weeklyTrendSample: stats.weeklyTrend?.[0], - stats, - }); + lastFetchTimeRef.current = now; } catch (err) { const error = err instanceof Error ? err : new Error(String(err)); log.error("Failed to fetch statistics", error); setError(error); } finally { setLoading(false); + fetchInProgressRef.current = false; } - }, [user?.id, getToken, statistics, lastFetchTime]); + }, [user?.id, getToken]); const clearCache = useCallback(() => { setStatistics(null); + statisticsRef.current = null; setLoading(false); setLastFetchTime(0); + lastFetchTimeRef.current = 0; setError(null); - log.debug("Statistics cache cleared"); + fetchInProgressRef.current = false; }, []); useEffect(() => { @@ -100,28 +105,25 @@ export function StatisticsProvider({ if (!user?.id) return; try { + fetchInProgressRef.current = true; setLoading(true); setError(null); - log.debug("Force fetching statistics", { userId: user.id }); const token = await getToken(); const stats = await getUserStatistics(user.id, token); setStatistics(stats); - setLastFetchTime(Date.now()); - log.debug("Statistics force fetched and cached", { - userId: user.id, - hasWeeklyTrend: !!stats.weeklyTrend, - weeklyTrendLength: stats.weeklyTrend?.length || 0, - weeklyTrendSample: stats.weeklyTrend?.[0], - stats, - }); + statisticsRef.current = stats; + const now = Date.now(); + setLastFetchTime(now); + lastFetchTimeRef.current = now; } catch (err) { const error = err instanceof Error ? err : new Error(String(err)); log.error("Failed to force fetch statistics", error); setError(error); } finally { setLoading(false); + fetchInProgressRef.current = false; } }, [user?.id, getToken]);