useSmartPolling's backoff only updates currentIntervalRef — the running setInterval never slows down, yet isBackingOff flips isLive to false

Open
#569 5 comments 0 reactions 1 assignee View on GitHub

Maintainers usually reply within 1 day

@Biglamar is already working on this.

Since Sep 27, 2026.

  • #577 by @Biglamar — open
  • #581 by @PINYOPATTANAWASANPORN — open
  • #809 by @Biglamar — open

Assessment

This issue has not been assessed yet.

Description

bug good first issue performance Stellar Wave

Problem

When the data is unchanged unchangedThreshold times in a row, useSmartPolling computes a longer interval:

const newInterval = Math.min(currentIntervalRef.current * backoffMultiplier, maxBackoff);
if (newInterval > currentIntervalRef.current) {
  currentIntervalRef.current = newInterval;
  dispatch({ type: 'START_BACKOFF' });
}

But the interval is only ever created with setInterval(fetchData, currentIntervalRef.current): at mount, and again when the tab becomes visible. Changing currentIntervalRef.current afterwards has no effect on the running timer. setInterval captured the delay when it was created. The same is true in reverse: refetch() and a detected change reset the ref back to interval, but the timer isn't rescheduled.

Impact

  • The documented goal of backing off to 30s (maxBackoff: 30000 in useBountyStatus) to reduce load on a quiet bounty never happens. Requests keep going out every 5s (BountyStatus) or every 2s (ClaimButton) for as long as the page is open.
  • isBackingOff still becomes true, and useBountyStatus computes isLive: isPolling && !isBackingOff. So BountyStatus stops showing the "live" indicator while the hook is in fact still polling at full speed. The UI reports the opposite of what's actually happening.

Suggested fix

Reschedule whenever the effective interval changes:

  • use a self-scheduling setTimeout chain that reads currentIntervalRef.current each time,
  • or clearInterval plus a new setInterval inside the backoff and reset branches.

Add a fake-timer test: with an unchanged fetchFn, after the threshold the gap between calls grows, up to maxBackoff, and it resets after a change or refetch().

Related: #46, #359. This is independent of the "polling stops after the first re-render" problem. Even with that fixed, backoff still wouldn't apply.

Dominant language
TypeScript
Stars
1
Forks
94
Avg merge
1h 2m
Merged PRs (30d)
25

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from MergeFi/frontend

All issues in MergeFi/frontend

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.