- Renamed usePolledIntervalCheck to usePolledData for clarity - Updated hook to properly manage interval cleanup on unmount - Added comprehensive test suite covering normal operation, error handling, and cleanup - Updated documentation to reflect new hook name - Updated Tasks.md to track progress Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2.3 KiB
2.3 KiB
React Hook Fetch Cancellation
This folder follows a shared convention for network fetch cancellation in React hooks.
Patterns
1. Hooks with manual refresh
Hooks that expose a refresh() callback must use a long-lived AbortController stored in a ref:
- `const abortRef = useRef<AbortController | null>(null);
- Call
abortRef.current?.abort()before starting a new request. - Create a fresh controller before every
refresh()invocation. - Pass
controller.signalto the API function. - In the cleanup effect, abort the controller when the hook unmounts.
- After each
await, checksignal.abortedbefore updating state.
This prevents stale responses from overwriting newer results and avoids React state updates after unmount.
2. One-shot mount-only requests
Hooks that only fetch once inside useEffect and do not expose a manual refresh may use a local controller:
- Create
const controller = new AbortController();inside the effect. - Pass
controller.signalto the request. - Abort it in the effect cleanup.
- This is the simplest correct pattern for single-fetch hooks.
3. Do not use boolean cancelled flags for network requests
A boolean cancelled flag is not sufficient because it does not stop the underlying fetch. Abort signals are the correct cancellation mechanism for fetch-based hooks.
Polling with Drift Correction
The usePolledData hook implements drift-corrected polling to maintain accurate polling intervals despite variable fetch durations.
How it works
- Uses self-scheduling timeouts instead of fixed
setInterval - Tracks elapsed time from poll start to completion with
performance.now() - Calculates next delay as
Math.max(0, pollInterval - elapsed) - Schedules the next poll with drift compensation in the
onSuccesscallback - If a fetch takes longer than
pollInterval, the next poll starts immediately (delay = 0)
Why this matters
With fixed setInterval:
- If a fetch takes 2 seconds and
pollIntervalis 5 seconds - Actual polling interval becomes ~7 seconds (2s fetch + 5s interval)
- Effective polling rate drifts and wastes bandwidth
With drift correction:
- Total time from poll start to next poll start is always ~5 seconds
- Fetch duration doesn't affect the long-term polling rate
- Bandwidth and CPU usage remain consistent