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) {
|
if (nextHtml !== currentHtml) {
|
||||||
editor.commands.setContent(nextHtml, { emitUpdate: true });
|
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]);
|
}, [signatureIdentity?.id, signatureIdentity?.htmlSignature, signatureIdentity?.textSignature, signatureSeparatorEnabled, signaturePosition, mode, plainTextMode]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1331,6 +1331,10 @@ export function EmailViewer({
|
|||||||
}, markAsReadDelay);
|
}, markAsReadDelay);
|
||||||
|
|
||||||
return () => clearTimeout(timeout);
|
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]);
|
}, [email?.id, email?.keywords?.$seen, onMarkAsRead]);
|
||||||
|
|
||||||
// Reset external content permission and quick reply when email changes
|
// Reset external content permission and quick reply when email changes
|
||||||
@@ -2260,6 +2264,11 @@ export function EmailViewer({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
return [...jmapAttachments, ...tnefExtracted, ...embeddedExtracted];
|
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]);
|
}, [email?.attachments, smimeDecryptedAttachments, tnefHtml, tnefText, tnefAttachments, embeddedEmailUnwrapped, embeddedEmailAttachments, calendarInvitationParsingEnabled, hideInlineImageAttachments]);
|
||||||
|
|
||||||
// Measure attachment chips in the below-header row to determine how many fit
|
// Measure attachment chips in the below-header row to determine how many fit
|
||||||
@@ -2968,7 +2977,7 @@ export function EmailViewer({
|
|||||||
${wordHtmlCSS}
|
${wordHtmlCSS}
|
||||||
${darkModeCSS}
|
${darkModeCSS}
|
||||||
</style></head><body>${effectiveEmailContent.html}<style>html,body{height:auto!important;min-height:0!important;max-height:none!important}</style></body></html>`;
|
</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.
|
// Imperatively restore blocked external content inside the iframe document.
|
||||||
// Avoids re-rendering the iframe srcDoc (which would reload and flash) when
|
// 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;
|
if (autoMdnRef.current === email.id) return;
|
||||||
autoMdnRef.current = email.id;
|
autoMdnRef.current = email.id;
|
||||||
sendReadReceiptNow(true).catch(() => { autoMdnRef.current = null; });
|
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]);
|
}, [readReceiptResponse, shouldOfferReadReceipt, email?.id, sendReadReceiptNow]);
|
||||||
|
|
||||||
// Show loading skeleton while email is being fetched
|
// Show loading skeleton while email is being fetched
|
||||||
|
|||||||
@@ -25,11 +25,9 @@ export function ProComposeTabBody({ tabId, data }: ProComposeTabBodyProps) {
|
|||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const client = useAuthStore((s) => s.client);
|
const client = useAuthStore((s) => s.client);
|
||||||
const sendEmail = useEmailStore((s) => s.sendEmail);
|
const sendEmail = useEmailStore((s) => s.sendEmail);
|
||||||
const fetchEmails = useEmailStore((s) => s.fetchEmails);
|
|
||||||
const refreshCurrentMailbox = useEmailStore((s) => s.refreshCurrentMailbox);
|
const refreshCurrentMailbox = useEmailStore((s) => s.refreshCurrentMailbox);
|
||||||
const fetchScheduledEmails = useEmailStore((s) => s.fetchScheduledEmails);
|
const fetchScheduledEmails = useEmailStore((s) => s.fetchScheduledEmails);
|
||||||
const refreshScheduledMetadata = useEmailStore((s) => s.refreshScheduledMetadata);
|
const refreshScheduledMetadata = useEmailStore((s) => s.refreshScheduledMetadata);
|
||||||
const selectedMailbox = useEmailStore((s) => s.selectedMailbox);
|
|
||||||
const isScheduledView = useEmailStore((s) => s.isScheduledView);
|
const isScheduledView = useEmailStore((s) => s.isScheduledView);
|
||||||
const closeTab = useProTabStore((s) => s.closeTab);
|
const closeTab = useProTabStore((s) => s.closeTab);
|
||||||
const updateTabTitle = useProTabStore((s) => s.updateTabTitle);
|
const updateTabTitle = useProTabStore((s) => s.updateTabTitle);
|
||||||
@@ -116,7 +114,7 @@ export function ProComposeTabBody({ tabId, data }: ProComposeTabBodyProps) {
|
|||||||
console.error('Failed to send email:', error);
|
console.error('Failed to send email:', error);
|
||||||
toast.error(t('notifications.error_sending'));
|
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(() => {
|
const handleClose = useCallback(() => {
|
||||||
closeTab(tabIdRef.current);
|
closeTab(tabIdRef.current);
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ export function useMailboxDrop({ mailbox, onDropComplete, onSuccess, onError }:
|
|||||||
} finally {
|
} finally {
|
||||||
endDrag();
|
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();
|
const valid = isValidTarget();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user