Files
BanGUI/frontend/src/providers/NavigationCancellationContext.ts
Lukas 7ba1cf7ca2 feat: Implement global request lifecycle cancellation on route transitions
Adds a navigation-aware request cancellation mechanism that automatically
aborts all route-specific API requests when the user navigates to a
different route. This prevents silent state-update errors from responses
arriving after component unmount and conserves bandwidth by cancelling
now-irrelevant requests.

Key additions:
- NavigationCancellationContext: Context for managing route-specific signals
- NavigationCancellationProvider: Provider that detects route changes and
  aborts all signals from the previous route
- useNavigationAbortSignal hook: Allows components to subscribe to
  navigation-aware cancellation signals
- Comprehensive tests for the cancellation lifecycle
- Documentation in Web-Development.md for request lifecycle policy

The provider is placed in the app hierarchy between BrowserRouter and
AuthProvider, ensuring consistent cancellation behavior across all routes.

Long-lived background tasks (polling, session validation) can opt-out by
managing their own AbortController lifecycle.

Closes #23 from Tasks.md: No global cancellation policy on route transitions

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-28 09:58:59 +02:00

57 lines
1.9 KiB
TypeScript

/**
* Navigation-aware request cancellation context.
*
* Provides a global cancellation mechanism tied to route transitions.
* When the user navigates to a new route, all AbortSignals obtained from
* this context are automatically aborted, cancelling in-flight requests
* associated with the previous route.
*
* Long-lived background fetches (e.g., polling with long TTL) can opt-out
* by not using this context and instead managing their own lifecycle,
* or by checking the signal early in their lifecycle.
*
* Design notes:
* - Subscribers are notified immediately when navigation occurs
* - Multiple consumers can safely subscribe and get independent signals
* - Signals are generator functions to allow late binding
*/
import { createContext } from "react";
/**
* Provides a fresh AbortSignal tied to the current route lifecycle.
*
* Each call returns a new AbortSignal. When the user navigates,
* all previously-returned signals are aborted.
*/
export interface NavigationCancellationContextType {
/**
* Get an AbortSignal for the current route's request lifecycle.
*
* The signal will be aborted automatically when the user navigates
* to a different route. This is ideal for route-specific data fetches
* that should not persist across page transitions.
*
* Example:
* const signal = useNavigationAbortSignal();
* const { items } = useListData({
* fetcher: (sig) => fetchBans(sig || signal),
* // ...
* });
*
* @returns An AbortSignal that lives for the duration of the current route
*/
getNavigationSignal(): AbortSignal;
}
/**
* React context for navigation-aware cancellation.
*
* Wrap the application with `NavigationCancellationProvider` to enable
* automatic request cancellation on route transitions.
*/
export const NavigationCancellationContext =
createContext<NavigationCancellationContextType | null>(null);
NavigationCancellationContext.displayName = "NavigationCancellation";