From 7b3d5ce6627e63bb5e27ca8a7b8874240e404ec6 Mon Sep 17 00:00:00 2001 From: YaronZaki Date: Thu, 15 Oct 2026 17:31:33 +0100 Subject: [PATCH] perf(property-list): memoize property list row chunking --- src/components/VirtualizedPropertyGrid.tsx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/VirtualizedPropertyGrid.tsx b/src/components/VirtualizedPropertyGrid.tsx index 021def28..bf8668d8 100644 --- a/src/components/VirtualizedPropertyGrid.tsx +++ b/src/components/VirtualizedPropertyGrid.tsx @@ -1,5 +1,5 @@ 'use client'; -import React, { useRef, useEffect, useState } from 'react'; +import React, { useMemo, useRef, useEffect, useState } from 'react'; import { useVirtualizer } from '@tanstack/react-virtual'; import { PropertyCard } from './PropertyCard'; import type { Property } from '@/types/property'; @@ -34,10 +34,18 @@ export const VirtualizedPropertyGrid: React.FC = ( return () => window.removeEventListener('resize', updateColumns); }, [viewMode]); - const rowCount = Math.ceil(properties.length / columns); + // Chunk the listings once per (properties, columns) change instead of + // re-slicing the array for every virtual row on every render. + const rows = useMemo(() => { + const chunked: Property[][] = []; + for (let i = 0; i < properties.length; i += columns) { + chunked.push(properties.slice(i, i + columns)); + } + return chunked; + }, [properties, columns]); const rowVirtualizer = useVirtualizer({ - count: rowCount, + count: rows.length, getScrollElement: () => parentRef.current, estimateSize: () => (viewMode === 'grid' ? 450 : 200), overscan: 5, @@ -62,8 +70,7 @@ export const VirtualizedPropertyGrid: React.FC = ( className="list-none p-0 m-0" > {rowVirtualizer.getVirtualItems().map((virtualRow) => { - const startIndex = virtualRow.index * columns; - const itemsInRow = properties.slice(startIndex, startIndex + columns); + const itemsInRow = rows[virtualRow.index] ?? []; return (