Repository navigation
Description
What happened?
When a dashboard refreshes, most tiles keep showing the old result with no loading sign until the new data arrives. Only line and stacked-bar time charts pulse while they refetch. Number, table, bar and pie tiles look finished the whole time. You can't tell stale values from fresh ones, and with live refresh on you may act on numbers that are minutes old.
Expected: every tile shows that it is refreshing (for example the same effect-pulse the time charts use) while it keeps the previous result on screen.
Steps to reproduce
- Create a dashboard on the default
otel_logssource with four tiles: a line time chart, a Number tile (for examplecount()), a Table tile grouped byServiceName, and a Pie or Bar tile grouped bySeverityText. - Pick a time range large enough that each query takes a second or more. You can also throttle the network in dev tools.
- Click "Refresh dashboard", or turn on live refresh.
- Watch the tiles while the queries run. The time chart pulses. The number, table, bar and pie tiles keep the old values with no sign of loading, then switch to the new values.
How are you running HyperDX?
Found by reading the code on main at 6767349. It affects any deployment that uses the app's dashboards.
Where does it show up?
UI, on the dashboard page, in any browser.
Root cause
A refresh moves the time range forward, so each tile runs with a new query key (useDashboardRefresh.tsx#L27-L39). The tiles set placeholderData: prev => prev. With react-query v5 (package.json#L53, ^5.56.2), a query that shows placeholder data is in success state. So isLoading stays false for the whole refetch. Only isPlaceholderData and isFetching are true.
- Time charts handle this correctly. DBTimeChart.tsx#L487-L489 reads
isPlaceholderData, and DBTimeChart.tsx#L542-L547 adds it toisLoadingOrPlaceholder. That value driveseffect-pulseat HDXMultiSeriesTimeChart.tsx#L1627. - Number tile: DBNumberChart.tsx#L238-L243 uses placeholder data. DBNumberChart.tsx#L377 shows a loader only when
isLoading && !data, so a refresh shows no sign at all. - Table tile: DBTableChart.tsx#L291 uses the same
isLoading && !datacheck. - Bar and pie tiles: CategoricalChart.tsx#L59-L66 uses placeholder data but returns only
isLoading(L128-L137). DBBarChart.tsx#L101 and DBPieChart.tsx#L128 pulse onisLoading, which isfalseduring a refresh. - useChartConfig.tsx#L448-L451 passes
isPlaceholderDataandisFetchingthrough unchanged, so each tile has to handle them itself. Most don't.
Suggested fix
- Add a "refreshing" flag (
isPlaceholderData || isFetching) and use it in every tile, next to the existingisLoading && !datafirst-load check. - Return the flag from
useCategoricalChart, and make bar and pie pulse on it. - Apply the same
effect-pulse(or a small spinner in the tile header) to the number and table tiles. - One option is to return an
isRefreshingfield fromuseQueriedChartConfig, so new tile types get it without extra work.
Logs
None. Nothing fails; the UI just gives no feedback.
Activity
brandon-pereira commentedon Sep 24, 2026
Thanks for raising this! Sounds like an easy win to improve the UX. We are open to contributions on this!
KhemkaAkshat commentedon Sep 24, 2026
Hi, I'd like to work on this issue. I understand the root cause and the proposed approach. I'll update the affected tiles to handle isPlaceholderData || isFetching as the refreshing state while keeping the existing data visible, following the existing time-chart implementation.
Harshul1484 commentedon Sep 24, 2026
Hi @KhemkaAkshat, flagging this to avoid duplicate work: I've already put together a fix for the number, bar and pie tiles (pulsing on
isLoading || isPlaceholderData, matchingDBTimeChart, with unit tests) and asked to be vouched in #3209. @brandon-pereira, happy to go with whichever you prefer. If Akshat takes this one, I can pick up the table tile or another issue instead.KhemkaAkshat commentedon Sep 24, 2026
Thanks for the heads-up! @Harshul1484 I see that both the chart tiles and table tile are already covered by your PRs #3211 and #3212, so I'll avoid duplicating the work and pick up another issue.
Harshul1484 commentedon Sep 24, 2026
Thanks @KhemkaAkshat, appreciate it — good luck with the next one!
fix(app): pulse number, bar and pie tiles while a dashboard refreshes (…
brandon-pereira commentedon Sep 25, 2026
Thanks for the contributions @Harshul1484 - I have approved.
I see a few gaps though, worth additional work before closing the issue.
These 3 tile types all show a loading state instead of the new pattern of keeping the previous state with pulse effect, to be consistent we should also update those.
If anyone is open to improving these, please feel free. I will review them.
Thanks for improving the product!
Harshul1484 commentedon Sep 25, 2026
Thanks for the reviews! I'll take Search, Heatmap and Patterns, using the same keep-previous-data + pulse approach as #3211 and #3212.
fix(app): keep table tile rows on screen while a dashboard refreshes (#…
fix(app): keep heatmap tiles on screen while a dashboard refreshes (#…
Harshul1484 commentedon Sep 25, 2026
@brandon-pereira thanks for merging the heatmap fix! Here's where the gaps from your earlier comment stand:
While fixing those I found the same issue in two more places, so I opened small follow-ups:
Happy to change the scope of either if you'd rather handle them differently.
fix(app): pulse the list-bar and histogram charts while they refresh (#…