From 0179471113a17d2dc7409701f4dd3df1df4c3126 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Wed, 4 Mar 2026 18:30:49 -0500 Subject: [PATCH] fix(launcher): break reactive loop causing tab crash on Event Files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The $effect in launcher_presentation_view.svelte was calling load_ae_obj_id__event_presentation() on every prop update. The SWR pattern in that function always fires a background Dexie write, which triggered the upstream liveQuery, which updated the prop, which re-ran the $effect — creating an infinite loop that saturated the API and crashed the browser tab within 30-60 seconds. Fix: guard on last_loaded_id so the API call only fires when the presentation ID actually changes, not on every downstream re-render. Co-Authored-By: Claude Sonnet 4.6 --- .../(launcher)/launcher_presentation_view.svelte | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/routes/events/[event_id]/(launcher)/launcher_presentation_view.svelte b/src/routes/events/[event_id]/(launcher)/launcher_presentation_view.svelte index 1e6eb572..93ed660b 100644 --- a/src/routes/events/[event_id]/(launcher)/launcher_presentation_view.svelte +++ b/src/routes/events/[event_id]/(launcher)/launcher_presentation_view.svelte @@ -12,10 +12,18 @@ import { events_func } from '$lib/ae_events_functions'; import Event_launcher_file_cont from './launcher_file_cont.svelte'; - // Staggered Load: Trigger deep fetch only when component is active + // Staggered Load: Trigger deep fetch only when the presentation ID changes. + // WHY: The SWR pattern in load_ae_obj_id__event_presentation always fires a + // background API call that writes to Dexie. That Dexie write triggers the + // liveQuery upstream, which updates the lq__event_presentation_obj prop, + // which re-runs this $effect — creating an infinite loop that crashes the tab. + // Guarding on last_loaded_id breaks the loop: the effect only makes an API + // call when we see a new presentation ID, not on every downstream prop update. + let last_loaded_id: string | null = null; $effect(() => { const id = lq__event_presentation_obj?.event_presentation_id; - if (id) { + if (id && id !== last_loaded_id) { + last_loaded_id = id; events_func.load_ae_obj_id__event_presentation({ api_cfg: $ae_api, event_presentation_id: id,