Repository navigation
Conversation
vercel#4208 cleared refreshInterval inside the immutable middleware, but middleware runs after hook options and the context config have been merged, so it could not tell the two apart and disabled both. Record whether refreshInterval came from the hook itself before that merge, and only clear the value when it was inherited from a parent <SWRConfig>. Fixes vercel#4322
vjymisal0
force-pushed
the
fix-immutable-hook-refresh-interval
branch
from
September 21, 2026 06:37
70ba4df to
446e700
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4322
Problem
#4208 added
config.refreshInterval = 0to theimmutablemiddleware souseSWRImmutablewould ignore arefreshIntervalinherited from a parent<SWRConfig>.Middleware runs after hook options and the context config have been merged into a single object, so at that point the two sources are indistinguishable — the line disables both. A
refreshIntervalpassed directly to the hook has silently stopped working since 2.4.0:Fix
Record whether
refreshIntervalcame from the hook itself before the merge happens, using a symbol on the config object, and only clear the value in the middleware when that marker is absent.useSWRImmutablepreviously used the genericwithMiddlewarehelper; it now inlines the same normalize-and-append-middleware logic so it can set the marker.withMiddlewareitself is untouched, so other middleware users are unaffected. The symbol survives SWR's config merging (mergeObjectsis object spread, which copies symbol keys).Behavior after this change:
refreshIntervalfrom a parent<SWRConfig>→ still ignored (fix: Ensure useSWRImmutable overrides global refreshInterval #4208's case, its test still passes).refreshIntervalpassed to the hook → honored, and it overrides a global one.Tests
Added two regression tests under
describe('issue #4322'): a hook-levelrefreshIntervalpolls, and a hook-level value overrides a global one. Both fail on the current code (git stashon the source file → exactly these 2 fail) and pass with the fix.Verification
pnpm jest test/use-swr-immutable.test.tsx— 9/9 pass (7 existing + 2 new).pnpm types:checkandpnpm test-typingpass.pnpm oxlintandpnpm oxfmt --checkclean on the changed files.pnpm jest: 389 pass, 1 failure intest/use-swr-remote-mutation.test.tsx("should prevent race condition if triggered multiple times"). That failure reproduces identically on unmodifiedmainin this environment (verified viagit stash) — a pre-existing timing flake, unrelated to this change.