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
This commit is contained in:
@@ -51,14 +51,15 @@ export function MailSettingsPage() {
|
|||||||
try {
|
try {
|
||||||
const accs = await fetchAccounts();
|
const accs = await fetchAccounts();
|
||||||
setAccounts(accs);
|
setAccounts(accs);
|
||||||
if (accs.length > 0 && !selectedAccountId) {
|
if (accs.length > 0) {
|
||||||
setSelectedAccountId(accs[0].id);
|
setSelectedAccountId((prev) => prev || accs[0].id);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err: any) {
|
||||||
toast.error(err instanceof Error ? err.message : String(err));
|
toast.error(err?.message || err?.detail || 'Failed to load accounts');
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}, [selectedAccountId, toast]);
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => { loadAccounts(); }, [loadAccounts]);
|
useEffect(() => { loadAccounts(); }, [loadAccounts]);
|
||||||
|
|
||||||
@@ -79,8 +80,8 @@ export function MailSettingsPage() {
|
|||||||
smtp_port: 587,
|
smtp_port: 587,
|
||||||
password: '',
|
password: '',
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err: any) {
|
||||||
toast.error(err instanceof Error ? err.message : String(err));
|
toast.error(err?.message || err?.detail || 'Save failed');
|
||||||
} finally {
|
} finally {
|
||||||
setSaving(false);
|
setSaving(false);
|
||||||
}
|
}
|
||||||
@@ -95,8 +96,8 @@ export function MailSettingsPage() {
|
|||||||
} else {
|
} else {
|
||||||
toast.error(result.message);
|
toast.error(result.message);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err: any) {
|
||||||
toast.error(err instanceof Error ? err.message : String(err));
|
toast.error(err?.message || err?.detail || 'Connection test failed');
|
||||||
} finally {
|
} finally {
|
||||||
setTesting(null);
|
setTesting(null);
|
||||||
}
|
}
|
||||||
@@ -106,9 +107,13 @@ export function MailSettingsPage() {
|
|||||||
setSyncing(accountId);
|
setSyncing(accountId);
|
||||||
try {
|
try {
|
||||||
const result = await triggerSync(accountId);
|
const result = await triggerSync(accountId);
|
||||||
toast.success(t('mail.syncSuccess', { count: result.synced_count }));
|
if ((result as any)?.error) {
|
||||||
} catch (err) {
|
toast.error((result as any).error);
|
||||||
toast.error(err instanceof Error ? err.message : String(err));
|
} else {
|
||||||
|
toast.success(t('mail.syncSuccess'));
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
toast.error(err?.message || err?.detail || 'Sync failed');
|
||||||
} finally {
|
} finally {
|
||||||
setSyncing(null);
|
setSyncing(null);
|
||||||
}
|
}
|
||||||
@@ -120,8 +125,8 @@ export function MailSettingsPage() {
|
|||||||
await deleteAccount(accountId);
|
await deleteAccount(accountId);
|
||||||
setAccounts((prev) => prev.filter((a) => a.id !== accountId));
|
setAccounts((prev) => prev.filter((a) => a.id !== accountId));
|
||||||
toast.success(t('mail.accountDeleted'));
|
toast.success(t('mail.accountDeleted'));
|
||||||
} catch (err) {
|
} catch (err: any) {
|
||||||
toast.error(err instanceof Error ? err.message : String(err));
|
toast.error(err?.message || err?.detail || 'Delete failed');
|
||||||
}
|
}
|
||||||
}, [toast, t]);
|
}, [toast, t]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user