Skip to content

Frontend refactor#60

Merged
Chen-zexi merged 9 commits intomainfrom
frontend-refactor
Mar 9, 2026
Merged

Frontend refactor#60
Chen-zexi merged 9 commits intomainfrom
frontend-refactor

Conversation

@leo-Zhizhu
Copy link
Collaborator

Refactor frontend: Integrate TanStack Query for optimal data fetching

- Replace manual AbortControllers and useEffect polls with useQuery

- Implement intelligent caching and background refetch logic for dashboard and market data

- De-duplicate API requests and improve Largest Contentful Paint metric

# Conflicts:
#	web/src/pages/Dashboard/Dashboard.jsx
- Replace manual AbortControllers and useEffect polls with useQuery

- Implement intelligent caching and background refetch logic for dashboard and market data

- De-duplicate API requests and improve Largest Contentful Paint metric
@leo-Zhizhu leo-Zhizhu requested a review from Chen-zexi March 8, 2026 06:53
@leo-Zhizhu
Copy link
Collaborator Author

leo-Zhizhu commented Mar 8, 2026

Before: network before

After: network after

Before: performance before

After: performance after

@Chen-zexi
Copy link
Contributor

Code review

Found 3 issues:

  1. Missing snapshot prop on <MarketChart> — regression of bugfix ac7a650. The snapshotData is available and passed to <StockHeader>, but it was silently dropped from <MarketChart> during the extraction refactor. This breaks extended-hours close lines and after-hours price display.

)}
<MarketChart
ref={chartRef}
symbol={selectedStock}
interval={selectedInterval}
onIntervalChange={handleIntervalChange}
onCapture={handleCaptureChart}
onStockMeta={handleStockMeta}
onLatestBar={handleLatestBar}
quoteData={overviewData?.quote || null}
earningsData={overviewData?.earningsSurprises || null}
overlayData={overlayData}
stockMeta={chartMeta}
liveTick={wsPrices.get(selectedStock)?.barData || null}
wsStatus={wsStatus}
ginlixDataEnabled={ginlixDataEnabled}
/>
</div>
</div>

  1. Error swallowing in queryFn defeats TanStack Query retry and AbortError handling. The catch block returns fallback data on ALL errors including AbortError, which means: (a) retry: 1 global config is bypassed, (b) aborted queries cache fake data as "successful", (c) the query never enters error state. Re-throw abort errors and let real errors propagate so TanStack Query can retry.

return data;
} catch (error) {
// If the stock is bogus or fetch fails, fallback so UI has skeleton data
return {
stockInfo: {
Symbol: selectedStock,
Name: `${selectedStock} Corp`,
Exchange: 'NASDAQ',
},
realTimePrice: null,
snapshot: null,
};
}
},

  1. Background tab polling not suppressed — behavioral regression. The old code used document.hidden guards (added in 2b791f8) to skip API calls when the tab is hidden. TanStack Query v5's refetchIntervalInBackground defaults to true, so all polling queries now fire in hidden tabs. Add refetchIntervalInBackground: false to every query that uses refetchInterval.

queryFn: fetchMarketStatus,
refetchInterval: 60000,
staleTime: 30000,
});
// 2. Market Indices (Adaptive Polling: 30s open / 60s closed)
const isMarketOpen = marketStatus?.market === 'open' ||
(marketStatus && !marketStatus.afterHours && !marketStatus.earlyHours && marketStatus.market !== 'closed');
const { data: indices, isLoading: indicesLoading } = useQuery({
queryKey: ['dashboard', 'indices', INDEX_SYMBOLS],
queryFn: async () => {
const { indices: next } = await getIndices(INDEX_SYMBOLS);
return next;
},
// Using placeholderData provides standard fallback values instantly
// without populating the cache as "fresh", thereby triggering an immediate background fetch
placeholderData: () => INDEX_SYMBOLS.map((s) => fallbackIndex(normalizeIndexSymbol(s))),
refetchInterval: isMarketOpen ? 30000 : 60000,
staleTime: 10000,

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

leo-Zhizhu and others added 3 commits March 8, 2026 17:29
- Fix: Pass missing snapshotData prop to MarketChart in MarketView

- Fix: Remove error swallowing in useStockData to allow TanStack Query retries and aborts to function correctly

- Fix: Apply refetchIntervalInBackground: false to all polling hooks (Dashboard, Market, Watchlist, Portfolio, Automations) to suppress background fetching and save bandwidth
Resolve conflicts in Dashboard.jsx and useWatchlistData.js:
- Keep refactored hook-based architecture (useDashboardData, useOnboarding)
- Merge previousClose field from main into useWatchlistData
- Fix useOnboarding to use auth context instead of redundant API call
@Chen-zexi Chen-zexi merged commit aaaebd5 into main Mar 9, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants