diff --git a/src/renderer/src/components/editor/CombinedDiffViewer.tsx b/src/renderer/src/components/editor/CombinedDiffViewer.tsx index 62a55ad8270..f965cb25342 100644 --- a/src/renderer/src/components/editor/CombinedDiffViewer.tsx +++ b/src/renderer/src/components/editor/CombinedDiffViewer.tsx @@ -181,6 +181,7 @@ export default function CombinedDiffViewer({ const [clearNotesDialogOpen, setClearNotesDialogOpen] = useState(false) const [isClearingNotes, setIsClearingNotes] = useState(false) const [notesCopied, setNotesCopied] = useState(false) + const mountedRef = useRef(true) // Why: clipboard IPC can resolve after the combined diff unmounts; skip // copied feedback instead of starting a reset timer on a stale viewer. const notesCopyMountedRef = useRef(false) @@ -203,6 +204,13 @@ export default function CombinedDiffViewer({ scrollContainerRef.current = node notesCopyMountedRef.current = node !== null }, []) + + useEffect(() => { + mountedRef.current = true + return () => { + mountedRef.current = false + } + }, []) const loadSchedulerRef = useRef( createCombinedDiffLoadScheduler({ loadSection: (index) => loadSectionRef.current(index) @@ -906,13 +914,18 @@ export default function CombinedDiffViewer({ setIsClearingNotes(true) try { const ok = await clearDiffComments(file.worktreeId) + if (!mountedRef.current) { + return + } if (ok) { setClearNotesDialogOpen(false) } else { toast.error('Failed to clear notes.') } } finally { - setIsClearingNotes(false) + if (mountedRef.current) { + setIsClearingNotes(false) + } } }, [clearDiffComments, diffCommentCount, file.worktreeId, isClearingNotes])