fix: abort active stream on session switch and warn before closing during streaming
- Add useEffect cleanup to abort in-flight fetch when ChatView unmounts
(e.g., session switch via key={id} remount). This triggers the existing
server-side cleanup chain: saves partial message to DB, auto-denies
pending permissions. Also resets streamingSessionId and
pendingApprovalSessionId global state to prevent stale UI.
- Add beforeunload handler during streaming to show browser confirmation
dialog when user attempts to close the window/tab, preventing accidental
data loss. Listener is automatically removed when streaming ends.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
fa1023c483
commit
cf14791de0
1 file changed
+27
@@ -66,6 +66,33 @@ export function ChatView({ sessionId, initialMessages = [], initialHasMore = fal
|
||||
}, [sessionId]);
|
||||
const abortControllerRef = useRef<AbortController | null>(null);
|
||||
|
||||
// Abort active stream on unmount (e.g., session switch via key={id} remount).
|
||||
// This triggers the existing server-side cleanup chain:
|
||||
// fetch abort → request.signal 'abort' → route abortController.abort()
|
||||
// → collectStreamResponse catch block saves partial message to DB
|
||||
// → permission-registry abort handler auto-denies pending permissions
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (abortControllerRef.current) {
|
||||
abortControllerRef.current.abort();
|
||||
abortControllerRef.current = null;
|
||||
}
|
||||
setStreamingSessionId('');
|
||||
setPendingApprovalSessionId('');
|
||||
};
|
||||
}, [setStreamingSessionId, setPendingApprovalSessionId]);
|
||||
|
||||
// Warn before closing window/tab while streaming to prevent accidental data loss
|
||||
useEffect(() => {
|
||||
if (!isStreaming) return;
|
||||
const handler = (e: BeforeUnloadEvent) => {
|
||||
e.preventDefault();
|
||||
e.returnValue = '';
|
||||
};
|
||||
window.addEventListener('beforeunload', handler);
|
||||
return () => window.removeEventListener('beforeunload', handler);
|
||||
}, [isStreaming]);
|
||||
|
||||
// Ref to keep accumulated streaming content in sync regardless of React batching
|
||||
const accumulatedRef = useRef('');
|
||||
// Refs to track tool data reliably across closures (state reads can be stale)
|
||||
|
||||
Reference in new issue
Block a user