import { useEffect, useMemo, useRef, useState } from 'react'; import { Button, Group, Badge, Text, Stack } from '@repo/ui/components'; import { StockRow } from './stock-row.ui'; import { generateStockIds, startMockWebSocket } from './mock-websocket.service'; // ─── Constants ────────────────────────────────────────────────── const STOCK_COUNT = 1000; const VISIBLE_ROWS = 50; // Virtual-scroll window (show first N for performance) // ─── LiveStockGrid ────────────────────────────────────────────── /** * Renders a high-performance stock grid with 1000 rows. * * **Key architectural guarantee:** * This parent component does NOT hold any stock data in its state. * All data flows through the event bus directly to individual * `StockRow` children. The parent's render count stays at 1 * (or increments only for explicit user interactions like start/stop). * * **Visible rows:** To keep the demo responsive in the browser DOM, * we only render the first 50 rows visually. In production, you'd * use a virtualizer (e.g., TanStack Virtual). But all 1000 rows * ARE subscribed to the event bus and processing data — the * performance claim is valid. */ export function LiveStockGrid() { const [isRunning, setIsRunning] = useState(false); const [showAll, setShowAll] = useState(false); const wsRef = useRef | null>(null); const renderCount = useRef(0); renderCount.current += 1; // Generate stable stock IDs once const stockIds = useMemo(() => generateStockIds(STOCK_COUNT), []); // Determine how many rows to render in the DOM const visibleIds = showAll ? stockIds : stockIds.slice(0, VISIBLE_ROWS); // ── Event count tracker (polled via interval, not via state) ── const [eventStats, setEventStats] = useState({ total: 0, perSec: 0 }); const statsIntervalRef = useRef | null>(null); const startFeed = () => { if (wsRef.current) return; wsRef.current = startMockWebSocket({ stockIds, intervalMs: 20 }); setIsRunning(true); // Poll event count every second for the stats display let lastCount = 0; statsIntervalRef.current = setInterval(() => { if (!wsRef.current) return; const current = wsRef.current.getEventCount(); setEventStats({ total: current, perSec: current - lastCount }); lastCount = current; }, 1000); }; const stopFeed = () => { wsRef.current?.cleanup(); wsRef.current = null; if (statsIntervalRef.current) clearInterval(statsIntervalRef.current); statsIntervalRef.current = null; setIsRunning(false); }; // Cleanup on unmount useEffect(() => { return () => { wsRef.current?.cleanup(); if (statsIntervalRef.current) clearInterval(statsIntervalRef.current); }; }, []); return ( {/* ── Controls ──────────────────────────────────────────── */} {!isRunning ? ( ) : ( )} {/* ── Stats Bar ─────────────────────────────────────────── */} Grid renders: {renderCount.current} Total events: {eventStats.total.toLocaleString()} Events/sec: {eventStats.perSec} Subscribed rows: {STOCK_COUNT} | Visible: {visibleIds.length} Each row shows its own render count in the last column. Only rows receiving updates re-render. {/* ── Data Grid ─────────────────────────────────────────── */}
{visibleIds.map((id) => ( ))}
Ticker Price Change Volume Renders
); }