useAsyncRetryLoading saved progress…

useAsyncRetry

Networks fail. A good UI doesn't just show "Something went wrong" — it shows a Retry button that re-runs the exact same request, not a blank one. useAsyncRetry builds that: it runs an async function, tracks the usual status/value/error, and exposes a retry() that replays the last call with the same arguments, plus an attempts counter for backoff or "tried 3 times" messaging.

Implement useAsyncRetry(asyncFunction, immediate = true). It returns { status, value, error, attempts, run, retry }. run(...args) executes and remembers its arguments; retry() re-runs with those same arguments. Every run and retry bumps attempts.

Signature

function useAsyncRetry(asyncFunction, immediate = true) {
  // returns { status, value, error, attempts, run, retry }
}

Examples

const { status, error, retry, attempts } = useAsyncRetry(() => loadFeed());
if (status === 'error') {
  return <button onClick={retry}>Retry (attempt {attempts + 1})</button>;
}
const { run, retry } = useAsyncRetry(searchUsers, false);
run('ada');   // searches "ada"
retry();      // re-runs searchUsers('ada'), NOT searchUsers()

Notes

  • Remember the last args — store them in a ref so retry replays the exact call, even after re-renders (a closure would go stale).
  • Retry re-runs, doesn't reset — it clears the previous error and moves back to pending, like a fresh run.
  • Count attempts — increment on every run and retry; handy for capped retries or backoff.
  • Stable run/retry — memoize both so they're safe as effect deps and button handlers.
Loading editor…