diff --git a/app/dashboard/transaction-history/page.tsx b/app/dashboard/transaction-history/page.tsx
index 104b5d3c..e9dc7ca9 100644
--- a/app/dashboard/transaction-history/page.tsx
+++ b/app/dashboard/transaction-history/page.tsx
@@ -19,10 +19,7 @@ import type {
Transaction,
TransactionStatus,
} from "@/components/Dashboard/TransactionHistoryItem";
-import { startOfDay, subDays, isSameDay, endOfDay, isBefore, isAfter } from "date-fns";
-// @ts-ignore
-import { FixedSizeList } from "react-window";
-const List = FixedSizeList as any;
+import { FixedSizeList as List } from "react-window";
type Direction = "all" | "sent" | "received";
@@ -38,6 +35,21 @@ export function getGroupKey(
return "earlier";
}
+export interface VirtualRowProps {
+ index: number;
+ style: React.CSSProperties;
+ data: Transaction[];
+}
+
+export const TransactionVirtualRow = ({ index, style, data }: VirtualRowProps) => {
+ const tx = data[index];
+ return (
+
+
+
+ );
+};
+
const TransactionHistoryPage = () => {
useSeo({
title: "Transaction History - RemitWise",
diff --git a/tests/unit/dashboard/transaction-history-virtualization.test.tsx b/tests/unit/dashboard/transaction-history-virtualization.test.tsx
new file mode 100644
index 00000000..6b0175b5
--- /dev/null
+++ b/tests/unit/dashboard/transaction-history-virtualization.test.tsx
@@ -0,0 +1,54 @@
+import { describe, it, expect } from "vitest";
+import { render, screen } from "@testing-library/react";
+import { FixedSizeList } from "react-window";
+import {
+ TransactionVirtualRow,
+} from "@/app/dashboard/transaction-history/page";
+import type { Transaction } from "@/components/Dashboard/TransactionHistoryItem";
+
+const ROW_COUNT = 250;
+
+function buildTransactions(count: number): Transaction[] {
+ return Array.from({ length: count }, (_, i) => ({
+ id: `tx-${i}`,
+ hash: `hash-${i}`,
+ type: "Send Money" as const,
+ amount: 100 + i,
+ currency: "USDC",
+ counterpartyName: `Recipient ${i}`,
+ counterpartyLabel: "To",
+ date: new Date(2026, 0, 1 + (i % 28)).toISOString(),
+ fee: 1.5,
+ status: "Completed" as const,
+ }));
+}
+
+describe("transaction history virtualization", () => {
+ it("renders a 250-row list via react-window without rendering every row into the DOM", () => {
+ const transactions = buildTransactions(ROW_COUNT);
+
+ render(
+
+
+ {TransactionVirtualRow}
+
+
+ );
+
+ // Only rows within (or just past) the visible window should be mounted --
+ // proof the list is actually virtualized, not just rendered in a
+ // fixed-height scroll container with all 250 rows present.
+ expect(screen.getByText("Recipient 0")).toBeInTheDocument();
+ expect(screen.queryByText(`Recipient ${ROW_COUNT - 1}`)).not.toBeInTheDocument();
+
+ const renderedRows = screen.getAllByText(/^Recipient \d+$/);
+ expect(renderedRows.length).toBeGreaterThan(0);
+ expect(renderedRows.length).toBeLessThan(ROW_COUNT);
+ });
+});