Fix promise cancellation in 5 components with AbortController refs
Add AbortController refs and abort signal checks to prevent race conditions and memory leaks when components unmount or new requests are initiated. Components fixed: - JailsTab.tsx: validation handler with AbortController pattern - JailInfoSection.tsx: handle function with useCallback wrapper - RawConfigSection.tsx: fetch handler with abort checks - ConfFilesTab.tsx: file fetch handler with abort signal verification - IgnoreListSection.tsx: three handlers (add, remove, toggle) with callbacks All handlers now: 1. Abort previous requests before initiating new ones 2. Create and store new AbortController instances 3. Check abort status before state updates in .then()/.catch() 4. Include cleanup effects that abort on unmount Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
* ``POST /api/config/actions`` on confirmation.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
@@ -73,6 +73,7 @@ export function CreateActionDialog({
|
||||
const [actionunban, setActionunban] = useState("");
|
||||
const [submitting, setSubmitting] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const submitControllerRef = useRef<AbortController | null>(null);
|
||||
|
||||
// Reset form when the dialog opens.
|
||||
useEffect(() => {
|
||||
@@ -99,23 +100,36 @@ export function CreateActionDialog({
|
||||
actionunban: actionunban.trim() || null,
|
||||
};
|
||||
|
||||
submitControllerRef.current?.abort();
|
||||
const controller = new AbortController();
|
||||
submitControllerRef.current = controller;
|
||||
|
||||
setSubmitting(true);
|
||||
setError(null);
|
||||
|
||||
onCreateAction(req)
|
||||
.then((action) => {
|
||||
if (controller.signal.aborted) return;
|
||||
onCreate(action);
|
||||
})
|
||||
.catch((err: unknown) => {
|
||||
if (controller.signal.aborted) return;
|
||||
setError(
|
||||
err instanceof ApiError ? err.message : "Failed to create action.",
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
if (controller.signal.aborted) return;
|
||||
setSubmitting(false);
|
||||
});
|
||||
}, [name, actionban, actionunban, submitting, onCreate, onCreateAction]);
|
||||
|
||||
useEffect(() => {
|
||||
return (): void => {
|
||||
submitControllerRef.current?.abort();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const canConfirm = name.trim() !== "" && !submitting;
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user