Case Study: Live Stock Dashboard (Part 2)
Refactor the dashboard by moving live data into an external store with selector-based subscriptions and wrapping heavy analytics work in transitions. This allows React 19 to maintain a responsive interface while analytics computation runs in the background.
In the previous lesson, we reduced per-render cost using React.memo and useMemo. However, we did not reduce the frequency of invalidation. The DashboardProvider still emits a full broadcast every 200 ms. As long as the data flow remains push-based, React’s scheduler must continue re-rendering components that do not actually need an update.
Priority-based update architecture
To reach 60fps under sustained load, we invert the data flow and shift to what we call the fast lane architecture:
The data layer (pull, not push): Instead of storing live prices inside context, we place mutable price data in an external store outside the React tree. Components access this store using
useSyncExternalStorewith selectors. A selector defines exactly which slice of the store the component depends on.Result:
TickerPanelreceives only the live prices slice.AnalyticsPanelreceives only its derived slice.Shell components receive nothing and never re-render.
React compares the selector’s output to the previous one before rendering; if they match, the render is skipped entirely, even under concurrent replay.
The interaction layer (urgent lane vs. transition lane): Analytics computations remain heavy; O(n) on every change. We cannot speed up the math, but we can structure the pipeline so the UI remains responsive. Wrapping user-driven updates (filters, sorting) in
startTransitiontells React:Update the input immediately (urgent lane). Recompute analytics later (transition lane).
React 19 can now defer, interrupt, or replay the heavy computation without blocking keystrokes or scrolls.
Caption: High-frequency store updates feed atomic selectors, while heavy computations run in a transition lane without blocking urgent UI work.