Add AbortSignal support to API functions for request cancellation

Add optional signal?: AbortSignal parameter to all API GET functions so they can be
cancelled when components unmount. This prevents state-update warnings and wasted
resources.

Changes:
- frontend/src/api/history.ts: fetchHistory, fetchIpHistory
- frontend/src/api/map.ts: fetchBansByCountry
- frontend/src/api/jails.ts: fetchJails, fetchActiveBans
- frontend/src/api/config.ts: fetchJailConfig, fetchInactiveJails, fetchJailConfigFiles,
  fetchFilterFiles (threads signal through fetchFilters), fetchFilterFile, fetchActionFiles,
  fetchActionFile
- frontend/src/api/blocklist.ts: fetchImportLog, previewBlocklist

Updated all calling hooks to pass the abort signal from their controllers:
- useHistory, useIpHistory
- useMapData
- useActiveBans
- useJails
- useConfigActiveStatus (fetchJails and fetchJailConfigs)
- useJailAdmin (fetchInactiveJails)
- useJailConfigDetail (fetchJailConfig)
- useImportLog (fetchImportLog)
- useBlocklists (previewBlocklist with AbortController)

Updated Docs/Web-Development.md to document the convention.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-23 08:33:28 +02:00
parent 1c5b2d36d9
commit 5a6cb640d8
16 changed files with 54 additions and 59 deletions

View File

@@ -35,7 +35,7 @@ export function useActiveBans(): UseActiveBansResult {
setLoading(true);
setError(null);
fetchActiveBans()
fetchActiveBans(ctrl.signal)
.then((res) => {
if (!ctrl.signal.aborted) {
setBans(res.bans);

View File

@@ -74,7 +74,8 @@ export function useBlocklists(): UseBlocklistsReturn {
);
const previewSource = useCallback(async (id: number): Promise<PreviewResponse> => {
return previewBlocklist(id);
const ctrl = new AbortController();
return previewBlocklist(id, ctrl.signal);
}, []);
return {

View File

@@ -66,8 +66,8 @@ export function useConfigActiveStatus(): UseConfigActiveStatusResult {
setError(null);
Promise.all([
fetchJails(),
fetchJailConfigs(),
fetchJails(ctrl.signal),
fetchJailConfigs(ctrl.signal),
])
.then(([jailsResp, configsResp]) => {
if (ctrl.signal.aborted) return;

View File

@@ -39,7 +39,7 @@ export function useHistory(query: HistoryQuery = {}): UseHistoryResult {
setLoading(true);
setError(null);
fetchHistory({ ...query, page })
fetchHistory({ ...query, page }, abortRef.current.signal)
.then((resp) => {
setItems(resp.items);
setTotal(resp.total);
@@ -85,7 +85,7 @@ export function useIpHistory(ip: string): UseIpHistoryResult {
setLoading(true);
setError(null);
fetchIpHistory(ip)
fetchIpHistory(ip, abortRef.current.signal)
.then((resp) => {
setDetail(resp);
})

View File

@@ -37,7 +37,7 @@ export function useImportLog(
setLoading(true);
setError(null);
fetchImportLog(page, pageSize, sourceId)
fetchImportLog(page, pageSize, sourceId, ctrl.signal)
.then((result) => {
if (!ctrl.signal.aborted) {
setData(result);

View File

@@ -49,7 +49,7 @@ export function useJailAdmin(): UseJailAdminResult {
setInactiveLoading(true);
setInactiveError(null);
fetchInactiveJails()
fetchInactiveJails(ctrl.signal)
.then((resp) => {
if (!ctrl.signal.aborted) {
setInactiveJails(resp.jails);

View File

@@ -32,7 +32,7 @@ export function useJailConfigDetail(name: string): UseJailConfigDetailResult {
setLoading(true);
setError(null);
fetchJailConfig(name)
fetchJailConfig(name, ctrl.signal)
.then((resp) => {
if (!ctrl.signal.aborted) {
setJail(resp.jail);

View File

@@ -44,7 +44,7 @@ export function useJails(): UseJailsResult {
setLoading(true);
setError(null);
fetchJails()
fetchJails(ctrl.signal)
.then((res) => {
if (!ctrl.signal.aborted) {
setJails(res.jails);

View File

@@ -66,7 +66,7 @@ export function useMapData(
abortRef.current?.abort();
abortRef.current = new AbortController();
fetchBansByCountry(range, origin, source, countryCode)
fetchBansByCountry(range, origin, source, countryCode, abortRef.current.signal)
.then((resp) => {
setData(resp);
})