-
Notifications
You must be signed in to change notification settings - Fork 436
fix(clerk-js): Suppress intermediate emissions from updateClient during setActive #7815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…ng setActive During setActive, the touch() call triggers a piggybacked client update via BaseResource._baseFetch, which calls updateClient() and emits state to React before setTransitiveState() runs. With useSyncExternalStore (unlike the old useState+addListener approach), each emission causes a synchronous re-render. This exposed the new orgId to components before the transitive state (undefined) was set, causing flickering and stale data issues during org switches. Gate the #emit() in updateClient with the existing __internal_setActiveInProgress flag so intermediate state from piggybacked client updates is suppressed. setActive emits the final state itself via #setTransitiveState or #updateAccessors.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: f47d344 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 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 |
2b54404 to
d3a7b54
Compare
📝 WalkthroughWalkthroughA guard was added to Clerk's 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. No actionable comments were generated in the recent review. 🎉 Comment |
@clerk/agent-toolkit
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/dev-cli
@clerk/expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
|
!snapshot |
|
Hey @jacekradko - the snapshot version command generated the following package versions:
Tip: Use the snippet copy button below to quickly install the required packages. npm i @clerk/agent-toolkit@0.3.0-snapshot.v20260210223332 --save-exact
npm i @clerk/astro@3.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/backend@3.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/chrome-extension@3.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/clerk-js@6.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/dev-cli@1.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/expo@3.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/expo-passkeys@1.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/express@2.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/fastify@2.7.0-snapshot.v20260210223332 --save-exact
npm i @clerk/localizations@4.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/msw@0.0.1-snapshot.v20260210223332 --save-exact
npm i @clerk/nextjs@7.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/nuxt@2.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/react@6.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/react-router@3.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/shared@4.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/tanstack-react-start@1.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/testing@2.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/ui@1.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/upgrade@2.0.0-snapshot.v20260210223332 --save-exact
npm i @clerk/vue@2.0.0-snapshot.v20260210223332 --save-exact |
Summary
updateClientwhen called duringsetActive(e.g. fromtouch()'s piggybacked client response)undefined) is set during org switches__internal_setActiveInProgressflag to gate#emit()inupdateClientRoot Cause
During
setActive,touch()triggersupdateClient()viaBaseResource._baseFetchclient piggybacking, which calls#emit()before#setTransitiveState()runs. With the migration fromuseState+addListenertouseSyncExternalStore, each emission causes a synchronous re-render (sync-priority lane updates to prevent tearing). This exposed the new orgId to components before the transitive state was set, causing flickering during org switches.Emission sequence before fix:
updateClient#emit(newOrg)→setTransitiveState#emit(undefined)→#updateAccessors#emit(newOrg)Emission sequence after fix:
setTransitiveState#emit(undefined)→#updateAccessors#emit(newOrg)Test plan
pnpm buildpassesSummary by CodeRabbit
Bug Fixes
Tests