fix(ui): prevent async listener leaks on back navigation
This commit is contained in:
parent
2618c2ce77
commit
b6e31f9312
3 changed files with 123 additions and 78 deletions
|
|
@ -66,10 +66,12 @@ export default function NotificationCenter() {
|
|||
}, [projectId]);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
let unlisten: (() => void) | null = null;
|
||||
|
||||
const setup = async () => {
|
||||
unlisten = await listen<NewNotificationEvent>("new-notification", (event) => {
|
||||
try {
|
||||
const cleanup = await listen<NewNotificationEvent>("new-notification", (event) => {
|
||||
const incoming = event.payload.notification;
|
||||
|
||||
if (projectId && incoming.project_id !== projectId) {
|
||||
|
|
@ -83,11 +85,22 @@ export default function NotificationCenter() {
|
|||
|
||||
void showSystemNotification(incoming);
|
||||
});
|
||||
|
||||
if (cancelled) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
unlisten = cleanup;
|
||||
} catch (error: unknown) {
|
||||
console.error("Failed to subscribe to notifications", error);
|
||||
}
|
||||
};
|
||||
|
||||
void setup();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
if (unlisten) {
|
||||
unlisten();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,9 +160,11 @@ export default function ProjectLiveAgent() {
|
|||
useEffect(() => {
|
||||
if (!projectId) return;
|
||||
|
||||
let cancelled = false;
|
||||
let stop: (() => void) | null = null;
|
||||
|
||||
void (async () => {
|
||||
const setup = async () => {
|
||||
try {
|
||||
const [unlistenMessage, unlistenStarted, unlistenChunk, unlistenFinished, unlistenError] =
|
||||
await Promise.all([
|
||||
listen<LiveEventPayload>("live-agent-message", (event) => {
|
||||
|
|
@ -217,17 +219,34 @@ export default function ProjectLiveAgent() {
|
|||
}),
|
||||
]);
|
||||
|
||||
stop = () => {
|
||||
const cleanup = () => {
|
||||
unlistenMessage();
|
||||
unlistenStarted();
|
||||
unlistenChunk();
|
||||
unlistenFinished();
|
||||
unlistenError();
|
||||
};
|
||||
})();
|
||||
|
||||
if (cancelled) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
stop = cleanup;
|
||||
} catch (err: unknown) {
|
||||
if (!cancelled) {
|
||||
setError(getErrorMessage(err));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void setup();
|
||||
|
||||
return () => {
|
||||
if (stop) stop();
|
||||
cancelled = true;
|
||||
if (stop) {
|
||||
stop();
|
||||
}
|
||||
};
|
||||
}, [projectId, selectedSessionId]);
|
||||
|
||||
|
|
|
|||
|
|
@ -76,18 +76,31 @@ export default function ProjectTasks() {
|
|||
|
||||
useEffect(() => {
|
||||
if (!projectId) return;
|
||||
let stop: (() => void) | null = null;
|
||||
let cancelled = false;
|
||||
let unlisten: (() => void) | null = null;
|
||||
|
||||
void (async () => {
|
||||
const unlisten = await listen<TaskEventPayload>("agent-task-updated", (event) => {
|
||||
void listen<TaskEventPayload>("agent-task-updated", (event) => {
|
||||
if (event.payload.project_id !== projectId) return;
|
||||
void refresh();
|
||||
})
|
||||
.then((cleanup) => {
|
||||
if (cancelled) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
unlisten = cleanup;
|
||||
})
|
||||
.catch((err: unknown) => {
|
||||
if (!cancelled) {
|
||||
setError(getErrorMessage(err));
|
||||
}
|
||||
});
|
||||
stop = unlisten;
|
||||
})();
|
||||
|
||||
return () => {
|
||||
if (stop) stop();
|
||||
cancelled = true;
|
||||
if (unlisten) {
|
||||
unlisten();
|
||||
}
|
||||
};
|
||||
}, [projectId]);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue