From 68a9415e996a2ad0cad52cc3fe1de43321aaae9b Mon Sep 17 00:00:00 2001 From: Agent Zero Date: Thu, 16 Jul 2026 22:20:41 +0200 Subject: [PATCH] fix(mail): infinite re-render in MailSettings + error handling + sync result - Fix infinite re-render: loadAccounts had selectedAccountId in deps causing repeated fetches every render; use functional setState and empty deps - Fix all error handlers in MailSettings: err?.message || err?.detail instead of String(err) - Fix sync result handling: backend returns {synced, error?} not {success, synced_count} - This infinite re-render was flooding the browser with requests, causing Network Error for SignatureManager API calls --- frontend/src/pages/MailSettings.tsx | 33 +++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/frontend/src/pages/MailSettings.tsx b/frontend/src/pages/MailSettings.tsx index 3cad4e5..f1b3298 100644 --- a/frontend/src/pages/MailSettings.tsx +++ b/frontend/src/pages/MailSettings.tsx @@ -51,14 +51,15 @@ export function MailSettingsPage() { try { const accs = await fetchAccounts(); setAccounts(accs); - if (accs.length > 0 && !selectedAccountId) { - setSelectedAccountId(accs[0].id); + if (accs.length > 0) { + setSelectedAccountId((prev) => prev || accs[0].id); } - } catch (err) { - toast.error(err instanceof Error ? err.message : String(err)); + } catch (err: any) { + toast.error(err?.message || err?.detail || 'Failed to load accounts'); } setLoading(false); - }, [selectedAccountId, toast]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); useEffect(() => { loadAccounts(); }, [loadAccounts]); @@ -79,8 +80,8 @@ export function MailSettingsPage() { smtp_port: 587, password: '', }); - } catch (err) { - toast.error(err instanceof Error ? err.message : String(err)); + } catch (err: any) { + toast.error(err?.message || err?.detail || 'Save failed'); } finally { setSaving(false); } @@ -95,8 +96,8 @@ export function MailSettingsPage() { } else { toast.error(result.message); } - } catch (err) { - toast.error(err instanceof Error ? err.message : String(err)); + } catch (err: any) { + toast.error(err?.message || err?.detail || 'Connection test failed'); } finally { setTesting(null); } @@ -106,9 +107,13 @@ export function MailSettingsPage() { setSyncing(accountId); try { const result = await triggerSync(accountId); - toast.success(t('mail.syncSuccess', { count: result.synced_count })); - } catch (err) { - toast.error(err instanceof Error ? err.message : String(err)); + if ((result as any)?.error) { + toast.error((result as any).error); + } else { + toast.success(t('mail.syncSuccess')); + } + } catch (err: any) { + toast.error(err?.message || err?.detail || 'Sync failed'); } finally { setSyncing(null); } @@ -120,8 +125,8 @@ export function MailSettingsPage() { await deleteAccount(accountId); setAccounts((prev) => prev.filter((a) => a.id !== accountId)); toast.success(t('mail.accountDeleted')); - } catch (err) { - toast.error(err instanceof Error ? err.message : String(err)); + } catch (err: any) { + toast.error(err?.message || err?.detail || 'Delete failed'); } }, [toast, t]);