From 2e10752a59d40909ece98629e03255a0dcd186bc Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Sun, 7 Jun 2026 17:55:56 -0400 Subject: [PATCH] fix(pwa): stop calendar remount/flash on re-render (Bug B root cause) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The calendar flashed whenever the event popup/form closed or a post-write events refetch landed. Root cause: CalendarContent was a function component DEFINED INSIDE CalendarShell's render and used as . A nested component has a new identity every render, so React unmounted+remounted its whole subtree — including — on ANY CalendarShell re-render. The earlier Bug B work only minimized re-renders (Zustand selectors) to dodge this; the resync-before-done fix made the post-write ['events'] refetch deliver changed data again, so the remount/flash returned. Fix: render the content as a plain JSX element value (const calendarContent) referenced at both layout sites instead of a nested component type. Element values reconcile in place across re-renders — no remount, no flash. --- apps/pwa/src/components/CalendarShell.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/apps/pwa/src/components/CalendarShell.tsx b/apps/pwa/src/components/CalendarShell.tsx index 8e1d6d1..1d58635 100644 --- a/apps/pwa/src/components/CalendarShell.tsx +++ b/apps/pwa/src/components/CalendarShell.tsx @@ -236,9 +236,15 @@ export function CalendarShell() { // ── Calendar content ─────────────────────────────────────────────────────── - // The content panel (right of sidebar on desktop, full-width on phone) - function CalendarContent() { - return ( + // The content panel (right of sidebar on desktop, full-width on phone). + // + // This is a plain JSX value, NOT a nested `function CalendarContent()` rendered + // as ``. A component defined inside render has a new identity + // every render, so React unmounts+remounts its entire subtree — including + // — on ANY CalendarShell re-render (popup/form close, post- + // write events refetch). That full remount is the "calendar flash" (Bug B). As + // an element value it reconciles in place across re-renders: no remount, no flash. + const calendarContent = (
)}
- ) - } + ) // ── Full layout ──────────────────────────────────────────────────────────── @@ -355,7 +360,7 @@ export function CalendarShell() { currentUserName={meQuery.data?.user.displayName ?? undefined} /> - + {calendarContent} {/* New Event FAB — phone: bottom-right floating action button (UI-SPEC §Interaction Contract) */} @@ -457,7 +462,7 @@ export function CalendarShell() { - + {calendarContent} {/* EventDetailPopover — standalone mode driven by Zustand openEventId */}