From c9d5b96fa9849362b5a4be03b16207ef9450eb45 Mon Sep 17 00:00:00 2001 From: ChrisCanin Date: Mon, 16 Mar 2026 09:38:09 -0700 Subject: [PATCH 1/7] fix(expo): override __internal_queryClient for React Native compatibility clerk-js uses rspack code-splitting to lazily load QueryClient via dynamic import('./query-core'). On React Native, Metro bundles everything into a single file, so rspack's chunk loading never resolves and __internal_queryClient stays undefined. The useClerkQueryClient hook falls back to a no-op mock proxy when the query client is undefined, causing hooks like useOrganizationList, useSessionList, etc. to silently return empty data. Fix: use Object.defineProperty to override the broken getter on the Clerk instance with a synchronous version that creates a QueryClient via require('@tanstack/query-core') on first access. --- .changeset/fix-query-client-rn.md | 5 +++++ .../provider/singleton/createClerkInstance.ts | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 .changeset/fix-query-client-rn.md diff --git a/.changeset/fix-query-client-rn.md b/.changeset/fix-query-client-rn.md new file mode 100644 index 00000000000..2ac86035d4a --- /dev/null +++ b/.changeset/fix-query-client-rn.md @@ -0,0 +1,5 @@ +--- +"@clerk/expo": patch +--- + +Fix `useOrganizationList` and other query-based hooks returning empty data on React Native by synchronously providing a `QueryClient` instance diff --git a/packages/expo/src/provider/singleton/createClerkInstance.ts b/packages/expo/src/provider/singleton/createClerkInstance.ts index 2a361bad54a..c4bfe5dc030 100644 --- a/packages/expo/src/provider/singleton/createClerkInstance.ts +++ b/packages/expo/src/provider/singleton/createClerkInstance.ts @@ -112,6 +112,26 @@ export function createClerkInstance(ClerkClass: typeof Clerk) { __internal_clerkOptions = { publishableKey, proxyUrl, domain }; __internal_clerk = new ClerkClass(publishableKey, { proxyUrl, domain }) as unknown as BrowserClerk; + // The clerk-js native bundle uses rspack code-splitting for the internal QueryClient. + // On React Native, rspack's chunk loading doesn't work (Metro bundles into a single file), + // so the dynamic import never resolves and __internal_queryClient stays undefined. + // This breaks hooks that depend on the query client (useOrganizationList, etc.). + // Override the getter to synchronously create a QueryClient on first access. + { + // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports + const { QueryClient } = require('@tanstack/query-core'); + let queryClient: InstanceType | undefined; + Object.defineProperty(__internal_clerk, '__internal_queryClient', { + get() { + if (!queryClient) { + queryClient = new QueryClient(); + } + return { __tag: 'clerk-rq-client', client: queryClient }; + }, + configurable: true, + }); + } + if (Platform.OS === 'ios' || Platform.OS === 'android') { // @ts-expect-error - This is an internal API __internal_clerk.__internal_createPublicCredentials = ( From 55b94545bd908391da77b4677219b90f20d0af27 Mon Sep 17 00:00:00 2001 From: ChrisCanin Date: Wed, 18 Mar 2026 11:04:03 -0700 Subject: [PATCH 2/7] fix(expo): remove unused eslint-disable directive --- packages/expo/src/provider/singleton/createClerkInstance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/expo/src/provider/singleton/createClerkInstance.ts b/packages/expo/src/provider/singleton/createClerkInstance.ts index c4bfe5dc030..e3ff934b468 100644 --- a/packages/expo/src/provider/singleton/createClerkInstance.ts +++ b/packages/expo/src/provider/singleton/createClerkInstance.ts @@ -118,7 +118,7 @@ export function createClerkInstance(ClerkClass: typeof Clerk) { // This breaks hooks that depend on the query client (useOrganizationList, etc.). // Override the getter to synchronously create a QueryClient on first access. { - // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports + // eslint-disable-next-line @typescript-eslint/no-require-imports const { QueryClient } = require('@tanstack/query-core'); let queryClient: InstanceType | undefined; Object.defineProperty(__internal_clerk, '__internal_queryClient', { From c94440a0b877e30ff548ee0a53c01ebd9cacaec1 Mon Sep 17 00:00:00 2001 From: ChrisCanin Date: Mon, 23 Mar 2026 15:39:45 -0700 Subject: [PATCH 3/7] fix(expo): add @tanstack/query-core as direct dependency The require('@tanstack/query-core') call fails with strict package managers like pnpm since it was only available as a transitive dep via @clerk/clerk-js. Pin to the same version clerk-js uses (5.90.16). --- packages/expo/package.json | 1 + pnpm-lock.yaml | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/expo/package.json b/packages/expo/package.json index 559e29df1f6..90f098dd3ae 100644 --- a/packages/expo/package.json +++ b/packages/expo/package.json @@ -114,6 +114,7 @@ "@clerk/clerk-js": "workspace:^", "@clerk/react": "workspace:^", "@clerk/shared": "workspace:^", + "@tanstack/query-core": "5.90.16", "base-64": "^1.0.0", "react-native-url-polyfill": "2.0.0", "tslib": "catalog:repo" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0a5b24875d4..152dbdd856f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -574,6 +574,9 @@ importers: '@clerk/shared': specifier: workspace:^ version: link:../shared + '@tanstack/query-core': + specifier: 5.90.16 + version: 5.90.16 base-64: specifier: ^1.0.0 version: 1.0.0 @@ -2607,7 +2610,7 @@ packages: '@expo/bunyan@4.0.1': resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==} - engines: {node: '>=0.10.0'} + engines: {'0': node >=0.10.0} '@expo/cli@0.22.26': resolution: {integrity: sha512-I689wc8Fn/AX7aUGiwrh3HnssiORMJtR2fpksX+JIe8Cj/EDleblYMSwRPd0025wrwOV9UN1KM/RuEt/QjCS3Q==} From 39512b0223a51fe1c9174febd75969f45a5b7423 Mon Sep 17 00:00:00 2001 From: ChrisCanin Date: Thu, 26 Mar 2026 14:58:11 -0700 Subject: [PATCH 4/7] fix(clerk-js): use dynamicImportMode eager in native rspack build Replace the expo-side QueryClient workaround with a one-line rspack config change that inlines all dynamic imports in the native build. This fixes useOrganizationList and other query-based hooks returning empty data on React Native. --- .changeset/fix-query-client-rn.md | 4 ++-- packages/clerk-js/rspack.config.js | 10 ++++++++++ .../provider/singleton/createClerkInstance.ts | 20 ------------------- pnpm-lock.yaml | 3 --- 4 files changed, 12 insertions(+), 25 deletions(-) diff --git a/.changeset/fix-query-client-rn.md b/.changeset/fix-query-client-rn.md index 2ac86035d4a..b6c01d72ab2 100644 --- a/.changeset/fix-query-client-rn.md +++ b/.changeset/fix-query-client-rn.md @@ -1,5 +1,5 @@ --- -"@clerk/expo": patch +"@clerk/clerk-js": patch --- -Fix `useOrganizationList` and other query-based hooks returning empty data on React Native by synchronously providing a `QueryClient` instance +Fix `useOrganizationList` and other query-based hooks returning empty data on React Native by using `dynamicImportMode: 'eager'` in the native rspack build so dynamic imports resolve synchronously diff --git a/packages/clerk-js/rspack.config.js b/packages/clerk-js/rspack.config.js index af1e2548990..43f0e0e733f 100644 --- a/packages/clerk-js/rspack.config.js +++ b/packages/clerk-js/rspack.config.js @@ -284,10 +284,20 @@ const prodConfig = ({ mode, env, analysis }) => { commonForProdChunked(), // Disable chunking for the native variant, since it's meant to be used in React Native // where dynamic chunk loading is not supported. + // `dynamicImportMode: 'eager'` inlines all dynamic import() modules directly into the + // bundle and resolves the returned Promise immediately, so rspack's async chunk-loading + // runtime (which doesn't work in Metro) is never emitted. { output: { publicPath: '', }, + module: { + parser: { + javascript: { + dynamicImportMode: 'eager', + }, + }, + }, optimization: { splitChunks: false, }, diff --git a/packages/expo/src/provider/singleton/createClerkInstance.ts b/packages/expo/src/provider/singleton/createClerkInstance.ts index e3ff934b468..2a361bad54a 100644 --- a/packages/expo/src/provider/singleton/createClerkInstance.ts +++ b/packages/expo/src/provider/singleton/createClerkInstance.ts @@ -112,26 +112,6 @@ export function createClerkInstance(ClerkClass: typeof Clerk) { __internal_clerkOptions = { publishableKey, proxyUrl, domain }; __internal_clerk = new ClerkClass(publishableKey, { proxyUrl, domain }) as unknown as BrowserClerk; - // The clerk-js native bundle uses rspack code-splitting for the internal QueryClient. - // On React Native, rspack's chunk loading doesn't work (Metro bundles into a single file), - // so the dynamic import never resolves and __internal_queryClient stays undefined. - // This breaks hooks that depend on the query client (useOrganizationList, etc.). - // Override the getter to synchronously create a QueryClient on first access. - { - // eslint-disable-next-line @typescript-eslint/no-require-imports - const { QueryClient } = require('@tanstack/query-core'); - let queryClient: InstanceType | undefined; - Object.defineProperty(__internal_clerk, '__internal_queryClient', { - get() { - if (!queryClient) { - queryClient = new QueryClient(); - } - return { __tag: 'clerk-rq-client', client: queryClient }; - }, - configurable: true, - }); - } - if (Platform.OS === 'ios' || Platform.OS === 'android') { // @ts-expect-error - This is an internal API __internal_clerk.__internal_createPublicCredentials = ( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 152dbdd856f..5d62235d895 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -574,9 +574,6 @@ importers: '@clerk/shared': specifier: workspace:^ version: link:../shared - '@tanstack/query-core': - specifier: 5.90.16 - version: 5.90.16 base-64: specifier: ^1.0.0 version: 1.0.0 From 80e30e735beb12089ea04b335e44772961a72ef5 Mon Sep 17 00:00:00 2001 From: Jacek Date: Thu, 26 Mar 2026 17:52:13 -0500 Subject: [PATCH 5/7] fix: update lockfile for @tanstack/query-core dependency --- pnpm-lock.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5d62235d895..152dbdd856f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -574,6 +574,9 @@ importers: '@clerk/shared': specifier: workspace:^ version: link:../shared + '@tanstack/query-core': + specifier: 5.90.16 + version: 5.90.16 base-64: specifier: ^1.0.0 version: 1.0.0 From 2f4655020401e3e7fc1d2fdedf5e0ba9d16eb835 Mon Sep 17 00:00:00 2001 From: Jacek Date: Thu, 26 Mar 2026 17:53:21 -0500 Subject: [PATCH 6/7] fix(expo): remove unused @tanstack/query-core dependency --- packages/expo/package.json | 1 - pnpm-lock.yaml | 3 --- 2 files changed, 4 deletions(-) diff --git a/packages/expo/package.json b/packages/expo/package.json index ca41c50ef8c..294cca6394d 100644 --- a/packages/expo/package.json +++ b/packages/expo/package.json @@ -114,7 +114,6 @@ "@clerk/clerk-js": "workspace:^", "@clerk/react": "workspace:^", "@clerk/shared": "workspace:^", - "@tanstack/query-core": "5.90.16", "base-64": "^1.0.0", "react-native-url-polyfill": "2.0.0", "tslib": "catalog:repo" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 152dbdd856f..5d62235d895 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -574,9 +574,6 @@ importers: '@clerk/shared': specifier: workspace:^ version: link:../shared - '@tanstack/query-core': - specifier: 5.90.16 - version: 5.90.16 base-64: specifier: ^1.0.0 version: 1.0.0 From abe0c47bb3b5b3efe7fcc007c8e65b8ba785f0a8 Mon Sep 17 00:00:00 2001 From: Jacek Date: Thu, 26 Mar 2026 18:37:45 -0500 Subject: [PATCH 7/7] fix(clerk-js): update bundlewatch limit for native bundle with eager imports --- packages/clerk-js/bundlewatch.config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/clerk-js/bundlewatch.config.json b/packages/clerk-js/bundlewatch.config.json index 45853fa48ba..2b6b08948a0 100644 --- a/packages/clerk-js/bundlewatch.config.json +++ b/packages/clerk-js/bundlewatch.config.json @@ -4,7 +4,7 @@ { "path": "./dist/clerk.browser.js", "maxSize": "67KB" }, { "path": "./dist/clerk.legacy.browser.js", "maxSize": "108KB" }, { "path": "./dist/clerk.no-rhc.js", "maxSize": "307KB" }, - { "path": "./dist/clerk.native.js", "maxSize": "66KB" }, + { "path": "./dist/clerk.native.js", "maxSize": "545KB" }, { "path": "./dist/vendors*.js", "maxSize": "7KB" }, { "path": "./dist/coinbase*.js", "maxSize": "36KB" }, { "path": "./dist/base-account-sdk*.js", "maxSize": "203KB" },