Skip to content

Commit c9d5b96

Browse files
committed
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.
1 parent 206d2b7 commit c9d5b96

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

.changeset/fix-query-client-rn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@clerk/expo": patch
3+
---
4+
5+
Fix `useOrganizationList` and other query-based hooks returning empty data on React Native by synchronously providing a `QueryClient` instance

packages/expo/src/provider/singleton/createClerkInstance.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,26 @@ export function createClerkInstance(ClerkClass: typeof Clerk) {
112112
__internal_clerkOptions = { publishableKey, proxyUrl, domain };
113113
__internal_clerk = new ClerkClass(publishableKey, { proxyUrl, domain }) as unknown as BrowserClerk;
114114

115+
// The clerk-js native bundle uses rspack code-splitting for the internal QueryClient.
116+
// On React Native, rspack's chunk loading doesn't work (Metro bundles into a single file),
117+
// so the dynamic import never resolves and __internal_queryClient stays undefined.
118+
// This breaks hooks that depend on the query client (useOrganizationList, etc.).
119+
// Override the getter to synchronously create a QueryClient on first access.
120+
{
121+
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
122+
const { QueryClient } = require('@tanstack/query-core');
123+
let queryClient: InstanceType<typeof QueryClient> | undefined;
124+
Object.defineProperty(__internal_clerk, '__internal_queryClient', {
125+
get() {
126+
if (!queryClient) {
127+
queryClient = new QueryClient();
128+
}
129+
return { __tag: 'clerk-rq-client', client: queryClient };
130+
},
131+
configurable: true,
132+
});
133+
}
134+
115135
if (Platform.OS === 'ios' || Platform.OS === 'android') {
116136
// @ts-expect-error - This is an internal API
117137
__internal_clerk.__internal_createPublicCredentials = (

0 commit comments

Comments
 (0)