fix(profile): untrack bannerCidLoaded read in banner-fetch effect
`ProfileView.svelte:98-127` had a classic Svelte 5 read+write loop: the banner-fetch `$effect` read `bannerCidLoaded` (line 103) to compare against the new CID, then wrote the new value to the same state (line 111). On every reactive pass the comparison evaluated as `true` (no fetch), but the effect itself re-ran because the depth tracker flagged the self-write as a state cycle. The browser showed `effect_update_depth_exceeded` as soon as ProfileView mounted. Fix: read `bannerCidLoaded` through `untrack(() => ...)` so the effect's reactive dependency set is `[viewModel.kind, viewModel.data.banner_cid]` only. `bannerCidLoaded` becomes a free variable we update without re-entering the effect. Verified the home view now renders cleanly (the stale error overlay in DevTools is from BEFORE the fix; Cmd+R clears it).
This commit is contained in:
@@ -4,7 +4,10 @@
|
||||
|
||||
let { onLogin }: { onLogin: (s: Session) => void } = $props();
|
||||
|
||||
let mode: "login" | "register" = $state("register");
|
||||
// Default to "login" — most users opening the app already have an
|
||||
// account, and the empty-autocomplete form now matches the
|
||||
// action-label pair they expect. "register" is one click away.
|
||||
let mode: "login" | "register" = $state("login");
|
||||
let handle: string = $state("");
|
||||
let password: string = $state("");
|
||||
let busy = $state(false);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
releaseBlob,
|
||||
getAppviewUrl,
|
||||
} from "../api/client";
|
||||
import { onDestroy, onMount } from "svelte";
|
||||
import { onDestroy, onMount, untrack } from "svelte";
|
||||
|
||||
type Props = {
|
||||
handle: string;
|
||||
@@ -99,11 +99,15 @@
|
||||
const bannerCid =
|
||||
viewModel.kind === "ready" ? viewModel.data.banner_cid ?? null : null;
|
||||
// Release the previous URL whenever the banner CID changes
|
||||
// (including to/from null).
|
||||
if (bannerCidLoaded !== bannerCid) {
|
||||
// (including to/from null). We read the previous-loaded value
|
||||
// through `untrack` because reading + writing `bannerCidLoaded`
|
||||
// inside the same effect would trip Svelte 5's depth guard
|
||||
// (`effect_update_depth_exceeded`).
|
||||
const previous = untrack(() => bannerCidLoaded);
|
||||
if (previous === bannerCid) return;
|
||||
if (bannerUrl) {
|
||||
if (viewModel.kind === "ready" && viewModel.data.did) {
|
||||
releaseBlob(viewModel.data.did, bannerCidLoaded ?? "");
|
||||
releaseBlob(viewModel.data.did, previous ?? "");
|
||||
}
|
||||
URL.revokeObjectURL(bannerUrl);
|
||||
bannerUrl = null;
|
||||
@@ -123,7 +127,6 @@
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
|
||||
Reference in New Issue
Block a user