From 452928760a78ddcae53ba0625b031a89d9474169 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Sun, 12 Apr 2026 22:35:35 +0200 Subject: [PATCH] fix(F-01): fix avatar upload persistence on profile page Replaced the one-shot initialized flag with a dirty flag that allows the useEffect to re-sync local state from server data after a successful save. Previously, once initialized was set to true, the effect never ran again so avatar changes were lost on refetch. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/client/components/ProfileSection.tsx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/client/components/ProfileSection.tsx b/src/client/components/ProfileSection.tsx index b466cbe..466ac3b 100644 --- a/src/client/components/ProfileSection.tsx +++ b/src/client/components/ProfileSection.tsx @@ -12,7 +12,7 @@ export function ProfileSection() { const [displayName, setDisplayName] = useState(""); const [bio, setBio] = useState(""); const [avatarUrl, setAvatarUrl] = useState(null); - const [initialized, setInitialized] = useState(false); + const [dirty, setDirty] = useState(false); const [message, setMessage] = useState<{ type: "success" | "error"; text: string; @@ -21,13 +21,12 @@ export function ProfileSection() { const fileInputRef = useRef(null); useEffect(() => { - if (profile && !initialized) { + if (profile && !dirty) { setDisplayName(profile.displayName ?? ""); setBio(profile.bio ?? ""); setAvatarUrl(profile.avatarUrl ?? null); - setInitialized(true); } - }, [profile, initialized]); + }, [profile, dirty]); async function handleSave(e: React.FormEvent) { e.preventDefault(); @@ -38,6 +37,7 @@ export function ProfileSection() { avatarUrl, bio: bio.trim() || undefined, }); + setDirty(false); setMessage({ type: "success", text: "Profile updated" }); } catch (err) { setMessage({ type: "error", text: (err as Error).message }); @@ -68,6 +68,7 @@ export function ProfileSection() { try { const result = await apiUpload<{ filename: string }>("/api/images", file); setAvatarUrl(result.filename); + setDirty(true); } catch { setMessage({ type: "error", text: "Avatar upload failed." }); } finally { @@ -147,7 +148,7 @@ export function ProfileSection() { {avatarUrl && (