diff --git a/frontend/src/components/config/ActionDetail.tsx b/frontend/src/components/config/ActionDetail.tsx index 45f2eb1..a0d106f 100644 --- a/frontend/src/components/config/ActionDetail.tsx +++ b/frontend/src/components/config/ActionDetail.tsx @@ -1,4 +1,4 @@ -import { useCallback, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import { Button, Field, Input, MessageBar, MessageBarBody } from "@fluentui/react-components"; import { Delete24Regular, LinkEdit24Regular } from "@fluentui/react-icons"; import type { ActionConfig } from "../../types/config"; @@ -18,22 +18,35 @@ export function ActionDetail({ action, onAssignClick, onRemovedFromJail }: Actio const [removingJail, setRemovingJail] = useState(null); const [removeError, setRemoveError] = useState(null); const { fetchRawContent, saveRawContent } = useActionRawFile(action.name); + const removeControllerRef = useRef(null); const handleRemoveFromJail = useCallback( (jailName: string): void => { + removeControllerRef.current?.abort(); + const controller = new AbortController(); + removeControllerRef.current = controller; + setRemovingJail(jailName); setRemoveError(null); onRemovedFromJail(jailName) .catch((err: unknown) => { + if (controller.signal.aborted) return; setRemoveError(err instanceof Error ? err.message : "Failed to remove action from jail."); }) .finally(() => { + if (controller.signal.aborted) return; setRemovingJail(null); }); }, [onRemovedFromJail], ); + useEffect(() => { + return (): void => { + removeControllerRef.current?.abort(); + }; + }, []); + return (