chore: resolve react-hooks/exhaustive-deps warnings
Goes through the 7 exhaustive-deps warnings individually: Added the genuinely-missing dependency (safe, no extra churn): - email-viewer useMemo: add effectiveEmailContent.hasStyleTag (used for hasOwnLayout; changes in lockstep with .html, closing a latent staleness gap). - pro-compose-tab-body handleSend: add refreshCurrentMailbox (stable zustand selector) and drop the stale fetchEmails/selectedMailbox deps — which left those two selectors entirely unused, so remove them too. - use-mailbox-drop handleDrop: add sourceMailboxId (changes in lockstep with draggedEmails, already a dep). Suppressed with a justified comment where depending on the whole object would regress behavior — these are intentional fine-grained deps: - email-composer signature-swap effect (keyed to signature fields + prev*Ref guards; whole signatureIdentity would re-splice the live editor). - email-viewer auto-mark-as-read (whole email would reset the delay timer on any unrelated field update). - email-viewer effective-attachments memo (derives from email.attachments; whole email would churn the list + its layout measurement). - email-viewer auto-MDN effect (email already captured via id + sendReadReceiptNow; autoMdnRef guards double-send). tsc --noEmit clean; eslint now reports 0 problems.
This commit is contained in:
committed by
Linus Rath
parent
0b7203df0f
commit
3516d3c727
@@ -647,6 +647,11 @@ export function EmailComposer({
|
||||
if (nextHtml !== currentHtml) {
|
||||
editor.commands.setContent(nextHtml, { emitUpdate: true });
|
||||
}
|
||||
// Intentionally keyed to the signature-relevant fields plus the internal
|
||||
// prev*Ref guards above; depending on the whole `signatureIdentity` object
|
||||
// would re-run on unrelated identity-field changes and re-splice the
|
||||
// signature into the live editor.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [signatureIdentity?.id, signatureIdentity?.htmlSignature, signatureIdentity?.textSignature, signatureSeparatorEnabled, signaturePosition, mode, plainTextMode]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1331,6 +1331,10 @@ export function EmailViewer({
|
||||
}, markAsReadDelay);
|
||||
|
||||
return () => clearTimeout(timeout);
|
||||
// Keyed to email id + $seen only: depending on the whole `email` object
|
||||
// would reset the mark-as-read delay timer whenever any unrelated email
|
||||
// field updates (e.g. a background re-fetch).
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [email?.id, email?.keywords?.$seen, onMarkAsRead]);
|
||||
|
||||
// Reset external content permission and quick reply when email changes
|
||||
@@ -2260,6 +2264,11 @@ export function EmailViewer({
|
||||
}));
|
||||
|
||||
return [...jmapAttachments, ...tnefExtracted, ...embeddedExtracted];
|
||||
// The memo derives only from `email.attachments` (findCalendarAttachment
|
||||
// scans that array); depending on the whole `email` object would rebuild the
|
||||
// attachment list — and its downstream layout measurement — on every email
|
||||
// field change.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [email?.attachments, smimeDecryptedAttachments, tnefHtml, tnefText, tnefAttachments, embeddedEmailUnwrapped, embeddedEmailAttachments, calendarInvitationParsingEnabled, hideInlineImageAttachments]);
|
||||
|
||||
// Measure attachment chips in the below-header row to determine how many fit
|
||||
@@ -2968,7 +2977,7 @@ export function EmailViewer({
|
||||
${wordHtmlCSS}
|
||||
${darkModeCSS}
|
||||
</style></head><body>${effectiveEmailContent.html}<style>html,body{height:auto!important;min-height:0!important;max-height:none!important}</style></body></html>`;
|
||||
}, [effectiveEmailContent.html, effectiveEmailContent.isHtml, isDark, emailHasNativeDarkMode]);
|
||||
}, [effectiveEmailContent.html, effectiveEmailContent.isHtml, effectiveEmailContent.hasStyleTag, isDark, emailHasNativeDarkMode]);
|
||||
|
||||
// Imperatively restore blocked external content inside the iframe document.
|
||||
// Avoids re-rendering the iframe srcDoc (which would reload and flash) when
|
||||
@@ -3414,6 +3423,9 @@ export function EmailViewer({
|
||||
if (autoMdnRef.current === email.id) return;
|
||||
autoMdnRef.current = email.id;
|
||||
sendReadReceiptNow(true).catch(() => { autoMdnRef.current = null; });
|
||||
// email is already captured via email?.id and sendReadReceiptNow (which
|
||||
// depends on `email`); the autoMdnRef guard prevents a double send.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [readReceiptResponse, shouldOfferReadReceipt, email?.id, sendReadReceiptNow]);
|
||||
|
||||
// Show loading skeleton while email is being fetched
|
||||
|
||||
@@ -25,11 +25,9 @@ export function ProComposeTabBody({ tabId, data }: ProComposeTabBodyProps) {
|
||||
const t = useTranslations();
|
||||
const client = useAuthStore((s) => s.client);
|
||||
const sendEmail = useEmailStore((s) => s.sendEmail);
|
||||
const fetchEmails = useEmailStore((s) => s.fetchEmails);
|
||||
const refreshCurrentMailbox = useEmailStore((s) => s.refreshCurrentMailbox);
|
||||
const fetchScheduledEmails = useEmailStore((s) => s.fetchScheduledEmails);
|
||||
const refreshScheduledMetadata = useEmailStore((s) => s.refreshScheduledMetadata);
|
||||
const selectedMailbox = useEmailStore((s) => s.selectedMailbox);
|
||||
const isScheduledView = useEmailStore((s) => s.isScheduledView);
|
||||
const closeTab = useProTabStore((s) => s.closeTab);
|
||||
const updateTabTitle = useProTabStore((s) => s.updateTabTitle);
|
||||
@@ -116,7 +114,7 @@ export function ProComposeTabBody({ tabId, data }: ProComposeTabBodyProps) {
|
||||
console.error('Failed to send email:', error);
|
||||
toast.error(t('notifications.error_sending'));
|
||||
}
|
||||
}, [client, sendEmail, fetchEmails, selectedMailbox, closeTab, data.sourceEmailId, data.mode, t, handleScheduledSendCreated]);
|
||||
}, [client, sendEmail, closeTab, data.sourceEmailId, data.mode, t, handleScheduledSendCreated, refreshCurrentMailbox]);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
closeTab(tabIdRef.current);
|
||||
|
||||
@@ -222,7 +222,7 @@ export function useMailboxDrop({ mailbox, onDropComplete, onSuccess, onError }:
|
||||
} finally {
|
||||
endDrag();
|
||||
}
|
||||
}, [client, mailbox, mailboxes, isValidTarget, moveEmailsToMailbox, crossAccountMoveEmails, draggedEmails, selectedEmailIds, clearSelection, refreshCurrentMailbox, endDrag, onDropComplete, onSuccess, onError]);
|
||||
}, [client, mailbox, mailboxes, isValidTarget, moveEmailsToMailbox, crossAccountMoveEmails, draggedEmails, sourceMailboxId, selectedEmailIds, clearSelection, refreshCurrentMailbox, endDrag, onDropComplete, onSuccess, onError]);
|
||||
|
||||
const valid = isValidTarget();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user