fix(signals): an optimistic store's first flight declares no transaction - #3264
Merged
Merged
Conversation
The flight-owned transaction (solidjs#3146) was declared for the uninitialized first ask too, so every transition-riding consumer — render()'s scheduled root insert included — was held until the initial fetch landed: the page stayed blank (content outside the boundary included) and the Loading boundary's fallback never showed, while createStore(fn, seed) and createOptimistic(fn, seed) in the same spot showed it. Nothing has committed on a first flight, so there is no truth to keep on screen and no optimistic state to protect: it now declares nothing, like the loading window (solidjs#2933). Refetch flights declare exactly as before, so bare optimistic writes during an in-flight refetch still ride the flight's transaction (solidjs#2951). Regressions in the solidjs#3146 suite (a user effect is what reproduces the hold) and in the web Loading spec through render(). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 0102a57 The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
ryansolid
added a commit
that referenced
this pull request
Sep 4, 2026
…ary warning Store-shaped variants of the deferred-root-mount design (deliberate: async at the root without a <Loading> boundary holds the mount until first truth and fires the dev warning; with a boundary the fallback shows and nothing warns). The memo-over-promise paths were pinned; the store paths were verified only by hand until now. Covers an optimistic store's first flight (post-#3264 it rides pending propagation alone) and a derived store, plus the boundary-catch case. Note for posterity: while writing these, the optimistic cases appeared to blank-hold through the boundary — a stale signals dist from before #3264; web tests consume dist, not src. Fresh build, all shapes correct. Co-authored-by: Cursor <cursoragent@cursor.com>
ryansolid
added a commit
that referenced
this pull request
Sep 4, 2026
…atch #3264/#3265/#3266 (+ dev-only #3263) land ~35 B on always-retained store paths, and #3262's handleAsync try/catch adds ~5 B to the core scenarios. A golf pass was attempted and measured strictly worse in every direction (helper extraction +29 B, full inline +70 B, has-trap arm merge -1/+7 B) — the graph is at its brotli optimum post-#3270. Ratchet per convention with audit notes: createStore 14.16 -> 14.20 KB, isPending/latest 10.04 -> 10.05, store-family app 26.25 -> 26.27. No package source changes, no changeset. Co-authored-by: Cursor <cursoragent@cursor.com>
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.
Summary
<Loading fallback={...}>around acreateOptimisticStore(fn, seed)never showed its fallback in client mode. The whole page stayed blank until the initial fetch landed — content outside the boundary included — whilecreateStore(fn, seed)andcreateOptimistic(fn, seed)in the same spot showed the fallback.ssr: truemasked it because the server streams the fallback and hydration is not a scheduled mount.Root cause
#3146 gave optimistic-store truth flights an owned, declared transaction.
declareFlightopened one for the uninitialized first flight too.render()'s root insert is scheduled and rides transitions, so the mount was stashed until the flight settled.Fix
A first flight declares nothing, the same rule the loading window (#2933) already follows: nothing has committed yet, so there is no truth to keep on screen and no optimistic state to protect. Refetch flights declare exactly as before; bare optimistic writes during an in-flight refetch still ride the flight's transaction (#2951).
Tests
tests/store/flight-owned-transaction.test.ts: first flight shows the boundary fallback, refetch keeps content, plus acreateStorecontrol. A user effect is what reproduces the hold; a render effect is not stashed by the transition.packages/web/test/loading.spec.tsx: the exact app shape throughrender(), asserting<h1>Poll</h1><div>Loading...</div>at mount and the list after landing.Both fail without the fix. The existing #3146 tests still pass.
🤖 Generated with Claude Code