SWR refreshWhenHidden is false: a hidden tab stops polling Sume jobs
SWR stops polling in a hidden tab by default, but a Sume job keeps running and billing. Store the job id and resume the poll on focus instead of resubmitting.

The answer
SWR's documented default is refreshWhenHidden = false: polling is skipped while the window is invisible, if refreshInterval is enabled. It also documents revalidateOnFocus = true, so when the tab comes back SWR revalidates. For a Sume job that is the right shape, with one rule: the job is not tied to the tab.
Sume's docs state that a client-side timeout does not cancel a job. It keeps running and still bills; you have only stopped watching. The same is true of a hidden tab, so keep the job id and read it again.
What the defaults do to a long render
A video or avatar-video job can run for minutes. If the user switches tabs after submitting, SWR pauses, the job continues, and on return the first revalidation reads the current state. Nothing is lost as long as the id is saved somewhere that survives a reload.
| Setting | Default | Consequence |
|---|---|---|
| refreshWhenHidden | false | No polling in a hidden tab |
| revalidateOnFocus | true | A status read when the tab regains focus |
| refreshWhenOffline | false | No polling while offline |
| revalidateOnReconnect | true | A read when the connection returns |
Persist the id, not the result
Write the job id to localStorage or your database right after the submit returns. On load, if an id is stored, mount the hook with it. The status route is cheap, and the response tells you whether the job is still running, finished, or ended in failed or canceled.
Do not resubmit because the page reloaded. A second submit is a second paid job unless you reuse the same Idempotency-Key with the same payload, which returns the original job. For refresh-safe flows, derive the key from your own record id and send it from your server.
// after the submit returns on your server route
localStorage.setItem("sume.job", submitted.data.request_id);
// on page load, pass the stored id to the polling hook
const id = localStorage.getItem("sume.job");
const { data } = useSumeJob(id);Cancel is only possible early
If the user abandons the page, you can cancel through the job's cancel URL, but only while cancelable is true. Sume's reference says cancel works before generation starts; afterwards it answers 409 job_generation_already_started. So leaving a job to finish and showing it on the next visit is usually the cheaper outcome than trying to cancel late.
A resume checklist
When the hook remounts with a stored id, handle each status explicitly: queued and processing keep the poll going, completed fetches the result and clears the stored id, and failed or canceled show the job's error and clear it as well. Treat an unknown id (404) as a stale record and drop it.
Because SWR revalidates on focus and on reconnect, a laptop that sleeps through a render wakes up to a fresh status read instead of a stale spinner. You do not need extra timers for that; the defaults already cover it. What you do need is the id, which is why the storage line comes before everything else.
If the user must not leave work unattended, a webhook to your server removes the tab from the picture entirely: the terminal event updates your database, and the page simply reads it.
Sources
Related posts
More in Developers
- Synthesia docs llms.txt vs the Sume Avatar 1.0 guide for AI assistants
Synthesia's docs offer llms.txt and .md pages for agents. Here is how to hand an AI assistant the Sume Avatar 1.0 guide, schema and tool list instead.
- Synthetic video for robot and driving tests: Seedance 2.5 API
ByteDance says Seedance 2.5 can make synthetic video for robots and driving edge cases. What a video API returns, and what you must add yourself.
- A teammate's music job id returns 404 with your API key: why
An API key reads only jobs its own member created in the workspace; anything else is 404 not_found. How to share a track or narration job with a teammate.
- Temporal Standalone Activity heartbeats: resume polling a Sume job
Heartbeats signal liveness and checkpoint progress for retries. Put the Sume job_id in the heartbeat so a retry resumes polling instead of paying again.
Written by Sume