Skip to content

Commit 8cc330d

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 da2b239 commit 8cc330d

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
@@ -63,6 +63,26 @@ export function createClerkInstance(ClerkClass: typeof Clerk) {
6363
const saveToken = tokenCache.saveToken;
6464
__internal_clerk = new ClerkClass(publishableKey) as unknown as BrowserClerk;
6565

66+
// The clerk-js native bundle uses rspack code-splitting for the internal QueryClient.
67+
// On React Native, rspack's chunk loading doesn't work (Metro bundles into a single file),
68+
// so the dynamic import never resolves and __internal_queryClient stays undefined.
69+
// This breaks hooks that depend on the query client (useOrganizationList, etc.).
70+
// Override the getter to synchronously create a QueryClient on first access.
71+
{
72+
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
73+
const { QueryClient } = require('@tanstack/query-core');
74+
let queryClient: InstanceType<typeof QueryClient> | undefined;
75+
Object.defineProperty(__internal_clerk, '__internal_queryClient', {
76+
get() {
77+
if (!queryClient) {
78+
queryClient = new QueryClient();
79+
}
80+
return { __tag: 'clerk-rq-client', client: queryClient };
81+
},
82+
configurable: true,
83+
});
84+
}
85+
6686
if (Platform.OS === 'ios' || Platform.OS === 'android') {
6787
// @ts-expect-error - This is an internal API
6888
__internal_clerk.__internal_createPublicCredentials = (

0 commit comments

Comments
 (0)