From 2788ec5c3f2082e20d5c89d64e54f5b9b0e30e6a Mon Sep 17 00:00:00 2001 From: Dexploarer <211557447+Dexploarer@users.noreply.github.com> Date: Sat, 25 Apr 2026 01:16:28 +0000 Subject: [PATCH] perf(conversations): memoize sidebar sort and avoid Date allocations * Wrap `sortedConversations` sorting logic in `useMemo` to prevent expensive re-computations on every render. * Optimize the sort comparator to use `localeCompare` on ISO date strings rather than allocating multiple `new Date()` objects per comparison. --- .jules/bolt.md | 3 +++ apps/app/src/components/ConversationsSidebar.tsx | 13 +++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000000..c81ab859c0 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-06-03 - Memoizing ISO date sorting +**Learning:** In React list components, `Array.sort()` with `new Date()` allocations is incredibly expensive (~10x slower than string comparison) on re-renders. `useMemo` combined with `localeCompare` on ISO date strings prevents this bottleneck. +**Action:** Always memoize derived lists and prefer lexicographical string comparisons over `Date` parsing for ISO 8601 timestamps. diff --git a/apps/app/src/components/ConversationsSidebar.tsx b/apps/app/src/components/ConversationsSidebar.tsx index 75d768bee2..786521beb4 100644 --- a/apps/app/src/components/ConversationsSidebar.tsx +++ b/apps/app/src/components/ConversationsSidebar.tsx @@ -2,7 +2,7 @@ * Conversations sidebar component — left sidebar with conversation list. */ -import { useEffect, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { useApp } from "../AppContext"; interface ConversationsSidebarProps { @@ -54,11 +54,12 @@ export function ConversationsSidebar({ } }, [editingId]); - const sortedConversations = [...conversations].sort((a, b) => { - const aTime = new Date(a.updatedAt).getTime(); - const bTime = new Date(b.updatedAt).getTime(); - return bTime - aTime; - }); + // ⚡ Bolt: Memoize the sorting of conversations and use string comparison instead of allocating new Date objects to prevent expensive computation on every re-render. + const sortedConversations = useMemo(() => { + return [...conversations].sort((a, b) => + b.updatedAt.localeCompare(a.updatedAt), + ); + }, [conversations]); const handleDoubleClick = (conv: { id: string; title: string }) => { setEditingId(conv.id);