From 17edcc2bc7caf6c3b00c77e1c6065178fa0e74b0 Mon Sep 17 00:00:00 2001 From: npub1cc3ha7z055mu0rwwu7806t2wt8mj3pvu0uv5mfp2c50dahaqhczshdalg6 Date: Wed, 8 Jul 2026 10:26:14 -0400 Subject: [PATCH] perf(desktop): memoise MessageActionBar, stabilise its onRemindLater callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finding [L4] MessageActionBar (Tier 3): the action bar re-rendered with every row render even when its props were unchanged. Wrap it in `React.memo`. The memo was dead on arrival, though — the row passed an inline `onRemindLater` arrow, a fresh function identity every render that defeated the shallow prop compare. Extract it to a `handleRemindLater` useCallback (deps [channelId, openReminder]); all other props are already stable (openReminder and handleReactionSelect are useCallbacks, setBadgeBurstEmoji is a state setter), so the memo now actually skips. Co-authored-by: Tyler Longwell Signed-off-by: Tyler Longwell --- .../features/messages/ui/MessageActionBar.tsx | 6 ++++-- .../src/features/messages/ui/MessageRow.tsx | 20 +++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/desktop/src/features/messages/ui/MessageActionBar.tsx b/desktop/src/features/messages/ui/MessageActionBar.tsx index d483ab2219..e5a36abbbf 100644 --- a/desktop/src/features/messages/ui/MessageActionBar.tsx +++ b/desktop/src/features/messages/ui/MessageActionBar.tsx @@ -326,7 +326,7 @@ function isCustomEmojiShortcode(emoji: string) { return emoji.startsWith(":") && emoji.endsWith(":"); } -export function MessageActionBar({ +export const MessageActionBar = React.memo(function MessageActionBar({ channelId, message, onDelete, @@ -549,4 +549,6 @@ export function MessageActionBar({ ); -} +}); + +MessageActionBar.displayName = "MessageActionBar"; diff --git a/desktop/src/features/messages/ui/MessageRow.tsx b/desktop/src/features/messages/ui/MessageRow.tsx index aa7e259c03..bbd79fc925 100644 --- a/desktop/src/features/messages/ui/MessageRow.tsx +++ b/desktop/src/features/messages/ui/MessageRow.tsx @@ -153,6 +153,17 @@ export const MessageRow = React.memo( } = useReactionHandler(message, onToggleReaction); const { openReminder, activeReminderEventIds } = useRemindLater(); const hasActiveReminder = activeReminderEventIds.has(message.id); + const handleRemindLater = React.useCallback( + (msg: TimelineMessage) => { + openReminder({ + eventId: msg.id, + channelId: channelId ?? "", + preview: msg.body.slice(0, 100), + authorPubkey: msg.pubkey ?? "", + }); + }, + [channelId, openReminder], + ); const mentionNames = React.useMemo( () => resolveMentionNames(message.tags, profiles), [profiles, message.tags], @@ -446,14 +457,7 @@ export const MessageRow = React.memo( onReactionSelect={ canToggleReactions ? handleReactionSelect : undefined } - onRemindLater={(msg) => { - openReminder({ - eventId: msg.id, - channelId: channelId ?? "", - preview: msg.body.slice(0, 100), - authorPubkey: msg.pubkey ?? "", - }); - }} + onRemindLater={handleRemindLater} onReply={onReply} onUnfollowThread={onUnfollowThread} reactionErrorMessage={reactionErrorMessage}