Repository navigation
docs(scoped-atoms): provide a family's atom for values from the server - #45
Merged
Merged
Conversation
A scoped atom that makes its own serializable atom gives two providers of one input two different atoms with one key, which fails the server render. Returning a family's atom from the scoped atom's factory keeps context access while every provider of one input holds the same atom. Tests pin both: the family version renders two same-input providers on the server and hydrates without computing, even across a remount; the plain version fails the render. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jarrednorrisdev
added a commit
that referenced
this pull request
Oct 9, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jarrednorrisdev
added a commit
that referenced
this pull request
Oct 9, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jarrednorrisdev
added a commit
that referenced
this pull request
Oct 9, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lead with the rule instead of a pattern: a family for data keyed by an id, a scoped atom for state that belongs to a place on the page. The failure a serializable scoped atom causes is the reason, and providing a family's atom from a scoped atom is now a one-line aside. A new test renders a thread that repeats an author through a plain family, on the server and hydrated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The docs again recommend providing a family's atom from a scoped atom for values from the server: the family gives one atom per id, the scoped atom keeps context access. The plain-family thread test from the last commit stays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jarrednorrisdev
added a commit
that referenced
this pull request
Oct 9, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.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.
Recommends a pattern for scoped atoms whose value comes from the server, and pins it with tests.
Docs note: #46, stacked on this PR, rewrites the scoped-atoms page and moves this PR's "Values from the server" section to the Hydration page in clearer form. Merge the two back to back; this PR's lasting changes are the tests and the
ScopedAtom.makedoc comment. Squash-merge it: its history includes a docs rewrite that was later reverted. Follow-up to #38.Background: a scoped atom makes one atom per provider component:
User.provide(id)creates it for that component's subtree, andUser.use()below reads it, like Svelte context. A family makes one atom per input:userAtom(1)returns the same atom wherever it's called. A serializable atom's value is sent from the server to the browser under its serialization key, and the registry stores it under that key, so atoms with one key share one value.The problem with the old advice
The docs said to put the input in the key:
The provider per comment is the point of the scoped atom: the card's parts get the author with
User.use(), withoutauthorIdbeing passed down to each of them.Bug: when one author comments twice, the server render fails with
Two different atoms share the serialization key "user-a". Each of their two providers made its own atom, and both have the keyuser-a. The pattern is also only scoped in name: because the value lives under its key, every copy shares it, and remounting a provider with{#key}doesn't reset it.The new advice
Make the atom a family, and if components below should still reach it without being passed the id, provide the family's atom with a scoped atom:
Every provider of one id now holds the same atom, so the page above renders on the server, and the browser hydrates both from the one server value.
User.use()works as before. No library code changes: this is a documented pattern, checked by tests.One limit, stated in the docs: a provider reads its input once, so if its
idprop can change, readuserAtom(id)with a getter instead.Step through the whole render, from the thread to the browser, with either advice: step 5 is where the old advice fails, at Alice's second comment, and the same step with the new advice.
Tests
In
test/scoped.browser.test.ts:{#key}.Locally, the scoped tests pass in Chromium and WebKit (6 tests each), and format, lint and type checks pass across the repo.
Decisions
ScopedAtom.familyhelper. The combination stays a documented two-line pattern; the docs steer people to a plain family first and to this combination only when the parts shouldn't be given the id.Where to look in the diff
apps/demo/src/routes/scoped-atoms/+page.md, and a pointer to it from the "Two different atoms share the serialization key" entry introubleshooting/+page.md.ScopedAtom.make's doc comment inpackages/effect-atom-svelte/src/ScopedAtom.ts.test/scoped.browser.test.ts. Fixtures:userFamilyandFamilyUserintest/fixtures/scoped-seed.ts,ssr-scoped-family.svelteandssr-scoped-same-input.svelte.🤖 Generated with Claude Code