From 8cc330dfc8982e485f0f1899bd30e5816a10e67f Mon Sep 17 00:00:00 2001 From: ChrisCanin Date: Mon, 16 Mar 2026 09:38:09 -0700 Subject: [PATCH] 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 d86b002cc6e..0bae142d1d0 100644 --- a/packages/expo/src/provider/singleton/createClerkInstance.ts +++ b/packages/expo/src/provider/singleton/createClerkInstance.ts @@ -63,6 +63,26 @@ export function createClerkInstance(ClerkClass: typeof Clerk) { const saveToken = tokenCache.saveToken; __internal_clerk = new ClerkClass(publishableKey) 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 = (