argus's review on the original fix: refresh() did a parallel one-off
fetch instead of calling the mount effect's self-rescheduling poll(),
so it never re-armed timerRef after firing. Wiring refresh() to run on
every visibilitychange-to-visible meant the very first tab-switch back
into focus would kill periodic polling for the rest of the session --
reproducing the exact staleness bug this branch set out to fix, just
delayed by one tab switch instead of immediate.
Fix: hoist poll into a ref set by the mount effect so refresh() invokes
the same self-rescheduling function rather than a parallel fetch that
drops the loop. Also gave the visibilitychange effect an empty
dependency array per the review's second note -- it only closes over
stable refs/setters, and now that Root's 1s ticker re-renders the
calling component every second, a deps-less effect would tear down and
reattach the listener that often for no reason.