From b0cfaeba60ea29c3abb259f13496861d87572c13 Mon Sep 17 00:00:00 2001 From: Nico Date: Thu, 4 Jun 2026 04:05:36 -0700 Subject: [PATCH] fix: memoize map bottom sheet summaries --- .../maps/LocationMapBottomSheet.jsx | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/maps/LocationMapBottomSheet.jsx b/frontend/src/components/maps/LocationMapBottomSheet.jsx index 72d056d..f533371 100644 --- a/frontend/src/components/maps/LocationMapBottomSheet.jsx +++ b/frontend/src/components/maps/LocationMapBottomSheet.jsx @@ -1,3 +1,4 @@ +import { useMemo } from "react"; import { DEFAULT_MAP_FILTERS, getMapObjectDisplayLabel, @@ -17,6 +18,7 @@ const DISPLAY_CONTROLS = [ ["showCompleted", "Bought"], ["showUnmapped", "Unmapped"], ]; +const EMPTY_ITEMS = []; export default function LocationMapBottomSheet({ mode, @@ -28,9 +30,9 @@ export default function LocationMapBottomSheet({ setLayersOpen, selectedObject, mapObjects = [], - selectedZoneItems, + selectedZoneItems = EMPTY_ITEMS, visibleAssignedItemCount = 0, - visibleUnmappedItems, + visibleUnmappedItems = EMPTY_ITEMS, unmappedItemCount, hiddenAreaCount, saving, @@ -48,9 +50,25 @@ export default function LocationMapBottomSheet({ onShowHiddenAreas, }) { const selectedTitle = getMapObjectDisplayLabel(selectedObject); - const selectedAssignedItems = selectedObject?.zone_id - ? (mapState?.items || []).filter((item) => String(item.zone_id || "") === objectZoneId(selectedObject)) - : []; + const selectedZoneId = objectZoneId(selectedObject); + const mapItems = mapState?.items || EMPTY_ITEMS; + const { assignedItemCount, selectedAssignedItems } = useMemo(() => { + const nextSelectedAssignedItems = []; + let nextAssignedItemCount = 0; + + mapItems.forEach((item) => { + if (!item.zone_id) return; + nextAssignedItemCount += 1; + if (selectedZoneId && String(item.zone_id) === selectedZoneId) { + nextSelectedAssignedItems.push(item); + } + }); + + return { + assignedItemCount: nextAssignedItemCount, + selectedAssignedItems: nextSelectedAssignedItems, + }; + }, [mapItems, selectedZoneId]); const hiddenSelectedItemCount = Math.max(0, selectedAssignedItems.length - selectedZoneItems.length); const hasHiddenSelectedItems = hiddenSelectedItemCount > 0; const selectedItemCountLabel = hasHiddenSelectedItems @@ -68,16 +86,24 @@ export default function LocationMapBottomSheet({ const showHeaderItemCount = mode !== "edit" && Boolean(selectedObject); const showEditorControls = mode === "edit" && canManage; const showSelectedObjectForm = Boolean(mode === "edit" && editorTool === "edit" && selectedObject); - const changedLayerCount = DISPLAY_CONTROLS.filter(([key]) => filters[key] !== DEFAULT_MAP_FILTERS[key]).length; - const assignedItemCount = (mapState?.items || []).filter((item) => item.zone_id).length; + const changedLayerCount = useMemo( + () => DISPLAY_CONTROLS.filter(([key]) => filters[key] !== DEFAULT_MAP_FILTERS[key]).length, + [filters] + ); const totalAreaCount = mapObjects.length; const visibleAreaCount = filters.showZones ? Math.max(0, totalAreaCount - hiddenAreaCount) : 0; const showMapOverview = mode !== "edit" && !selectedObject; - const unlinkedAreaCount = mapObjects.filter((object) => !objectZoneId(object)).length; + const unlinkedAreaCount = useMemo( + () => mapObjects.filter((object) => !objectZoneId(object)).length, + [mapObjects] + ); const showDraftOverview = mode === "edit" && editorTool === "edit" && !selectedObject; - const unmappedItemPreview = visibleUnmappedItems.slice(0, 8); + const unmappedItemPreview = useMemo( + () => visibleUnmappedItems.slice(0, 8), + [visibleUnmappedItems] + ); const overflowUnmappedItemCount = visibleUnmappedItems.length - unmappedItemPreview.length; const hiddenUnmappedItemCount = Math.max(0, unmappedItemCount - visibleUnmappedItems.length); const hasHiddenUnmappedItems =