Repository navigation
Seed test identities once and keep the identity list unique - #244
Merged
Merged
Conversation
Every full page load of `/` inserted five more identities. zustand's `useStore` hands React `getInitialState` as the server snapshot, so while the SSR'd page hydrates, `useSyncExternalStore` renders with the pre-hydration state (`identities: []`) even though `persist` has already read localStorage. The seeding effect ran on that stale closure and, since identity ids are derived deterministically from the identity number, wrote exact duplicates: 5 rows became 10, then 15. - `insertIdentity` is idempotent by id. - The persist `merge` dedupes persisted identities by id and tolerates a malformed list, which also heals profiles that already hold duplicates. - `/` seeds from the live store state once `persist.hasHydrated()` is true (or on `onFinishHydration`), instead of from the hook's `identities`. - Tests cover hydration dedupe, idempotent insert and malformed storage. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Sep 15, 2026
This branch was successfully 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.
Summary
Fixes the identity picker showing every test identity twice (then three times, and so on) after reloads.
Root cause. zustand's
useStorepassesapi.getInitialStateto React as the server snapshot. While the SSR'd page hydrates,useSyncExternalStorerenders with that pre-hydration snapshot,identities: [], even thoughpersisthas already hydrated synchronously from localStorage. The seeding effect on/ran on that stale closure and inserted five more identities on every full load. Ids are deterministic (ZkIdentity(String(idNumber))), so the duplicates carried identical ids.Fix.
insertIdentityis a no-op when the id already exists.mergededupes persisted identities by id (first occurrence wins) and falls back to the current list when the persisted field is not an array. Profiles that already contain duplicates heal on their next load./seeds fromuseIdentityStore.getState()oncepersist.hasHydrated()is true, otherwise viaonFinishHydration, instead of reading the hook'sidentities.Verification
tests/identity-store.test.tsinstalls an in-memory localStorage, imports the real store, and covers hydration dedupe, idempotent insert (including persisted output) and a malformedidentitiesfield.pnpm test: 28/28.pnpm typecheck,pnpm lint,pnpm run spellcheckclean.next dev: a profile holding 15 duplicated rows healed to 5 on reload; a cold profile seeded exactly 5 and stayed at 5 across three more loads;/select-idrenders one row per id.Not in this PR
The same stale snapshot makes the redirect effect on
/push/select-idbefore/id/<active>on every full load. Harmless, but worth a follow-up.🤖 Generated with Claude Code