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>
This commit is contained in:
56
frontend/src/providers/NavigationCancellationContext.ts
Normal file
56
frontend/src/providers/NavigationCancellationContext.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* 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";
|
||||
Reference in New Issue
Block a user