Most live dashboards start with useState and a setInterval, then end up with duplicate timers, stale closures, and requests firing from tabs nobody is looking at. This challenge flips the approach: the data lives in an external store, and your component only subscribes to it and owns the polling lifecycle.
๐งฉ Overview
You get a live metrics store and a dashboard to wire up. Use useSyncExternalStore to read from the store, then coordinate the first load, polling, manual refresh, tab visibility, and failure states without duplicating a single value in React state.
๐ https://www.reactchallenges.com/challenges/live-dashboard
โ Requirements
- Read from the provided store with
useSyncExternalStore(dashboardStore.subscribeanddashboardStore.getSnapshot);store.tsis hidden and must be used as-is. - On the first request, show the
Updatingโฆstatus and the skeleton, with no metric cards rendered. - After the first success, show
Liveand render four cards: active users, revenue, requests, and error rate. - Display the last successful update as
Updated at HH:MM:SS. - Start polling on mount when the document is visible, so the cards update without user interaction.
- During later polls (automatic or manual), keep the current cards on screen and show
Updatingโฆuntil the request succeeds. - Stop polling when the dashboard unmounts.
- Make the refresh button fetch immediately instead of waiting for the next interval, and disable it while updating.
- On failure, show
Errorwith the failure message and keep the last successful values on screen. - Retry on the next interval after a failure.
- When the document becomes hidden, show
Pausedand stop making requests. - When the document becomes visible again, refresh immediately and resume polling.
๐ก Notes
- Pass
getSnapshotdirectly touseSyncExternalStore. Don't copy the data intouseStateor build a new object inside the snapshot, or React will treat every read as a change. -
startreturns the cleanup function that stops polling. Return it from the effect so StrictMode's double mount doesn't leave two timers running. - Pausing is not only about clearing the interval โ decide what should happen to a request that is already in flight.
๐งช Tests
- Shows the skeleton and the updating status on mount
- Renders the four metrics after the first fetch
- Shows the time of the last successful update
- Polls every five seconds and updates the metrics
- Refreshes immediately when the refresh button is clicked
- Shows an error and keeps the last successful data
- Retries on the next interval after an error
- Pauses polling while the tab is hidden
- Refreshes and resumes polling when the tab becomes visible
- Stops polling when the dashboard unmounts
You'll finish with a dashboard that stays consistent while data changes underneath it: a single source of truth, a polling lifecycle with real cleanup, and stale-while-revalidate UX that keeps the last good values on screen instead of flashing a skeleton.
Top comments (0)