Skip to content

Commit 6da5615

Browse files
committed
handle init state
1 parent 7f5cb97 commit 6da5615

File tree

5 files changed

+43
-13
lines changed

5 files changed

+43
-13
lines changed

packages/shared/src/react/clerk-rq/use-clerk-query-client.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ function createRecursiveProxy(label: string): RecursiveMock {
5757

5858
const mockQueryClient = createRecursiveProxy('ClerkMockQueryClient') as unknown as QueryClient;
5959

60-
const useClerkQueryClient = (): QueryClient => {
60+
const useClerkQueryClient = (): [QueryClient, boolean] => {
6161
const clerk = useClerkInstanceContext();
6262

6363
// @ts-expect-error - __internal_queryClient is not typed
@@ -76,7 +76,9 @@ const useClerkQueryClient = (): QueryClient => {
7676
};
7777
}, [clerk, setQueryClientLoaded]);
7878

79-
return queryClient?.client || mockQueryClient;
79+
const isLoaded = typeof queryClient === 'object' && '__tag' in queryClient && queryClient.__tag === 'clerk-rq-client';
80+
81+
return [queryClient?.client || mockQueryClient, isLoaded];
8082
};
8183

8284
export { useClerkQueryClient };

packages/shared/src/react/clerk-rq/useBaseQuery.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,31 @@
44
*/
55

66
'use client';
7-
import type { QueryKey, QueryObserver, QueryObserverResult } from '@tanstack/query-core';
7+
import type { DefaultedQueryObserverOptions, QueryKey, QueryObserver, QueryObserverResult } from '@tanstack/query-core';
88
import { noop, notifyManager } from '@tanstack/query-core';
99
import * as React from 'react';
1010

1111
import type { UseBaseQueryOptions } from './types';
1212
import { useClerkQueryClient } from './use-clerk-query-client';
1313

14+
export type DistributivePick<T, K extends PropertyKey> = T extends unknown ? Pick<T, Extract<K, keyof T>> : never;
15+
16+
export type CommonQueryResult = 'data' | 'error' | 'isLoading' | 'isFetching' | 'status';
17+
1418
/**
1519
*
1620
*/
1721
export function useBaseQuery<TQueryFnData, TError, TData, TQueryData, TQueryKey extends QueryKey>(
1822
options: UseBaseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>,
1923
Observer: typeof QueryObserver,
20-
): QueryObserverResult<TData, TError> {
21-
const client = useClerkQueryClient();
22-
const defaultedOptions = client.defaultQueryOptions(options);
24+
): DistributivePick<QueryObserverResult<TData, TError>, CommonQueryResult> {
25+
const [client, isQueryClientLoaded] = useClerkQueryClient();
26+
const defaultedOptions = isQueryClientLoaded
27+
? client.defaultQueryOptions(options)
28+
: (options as DefaultedQueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>);
29+
30+
// Make sure results are optimistically set in fetching state before subscribing or updating options
31+
defaultedOptions._optimisticResults = 'optimistic';
2332

2433
const observer = React.useMemo(() => {
2534
return new Observer<TQueryFnData, TError, TData, TQueryData, TQueryKey>(client, defaultedOptions);
@@ -50,6 +59,19 @@ export function useBaseQuery<TQueryFnData, TError, TData, TQueryData, TQueryKey
5059
observer.setOptions(defaultedOptions);
5160
}, [defaultedOptions, observer]);
5261

62+
if (!isQueryClientLoaded) {
63+
// In this step we attempt to return a dummy result that matches RQ's pending state while on SSR or untill the query client is loaded on the client (after clerk-js loads).
64+
// When the query client is not loaded, we return the result as if the query was not enabled.
65+
// `isLoading` and `isFetching` need to be `false` because we can't know if the query will be enabled during SSR since most conditions really on client-only data that are available after clerk-js loads.
66+
return {
67+
data: undefined,
68+
error: null,
69+
isLoading: false,
70+
isFetching: false,
71+
status: 'pending',
72+
};
73+
}
74+
5375
// Handle result property usage tracking
5476
return !defaultedOptions.notifyOnChangeProps ? observer.trackResult(result) : result;
5577
}

packages/shared/src/react/clerk-rq/useQuery.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { QueryObserver } from '@tanstack/query-core';
44

55
import type { DefinedInitialDataOptions, UndefinedInitialDataOptions } from './queryOptions';
66
import type { DefinedUseQueryResult, UseQueryOptions, UseQueryResult } from './types';
7+
import type { CommonQueryResult, DistributivePick } from './useBaseQuery';
78
import { useBaseQuery } from './useBaseQuery';
89

910
export function useClerkQuery<
@@ -13,21 +14,25 @@ export function useClerkQuery<
1314
TQueryKey extends QueryKey = QueryKey,
1415
>(
1516
options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,
16-
): DefinedUseQueryResult<NoInfer<TData>, TError>;
17+
): DistributivePick<DefinedUseQueryResult<NoInfer<TData>, TError>, CommonQueryResult>;
1718

1819
export function useClerkQuery<
1920
TQueryFnData = unknown,
2021
TError = DefaultError,
2122
TData = TQueryFnData,
2223
TQueryKey extends QueryKey = QueryKey,
23-
>(options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>): UseQueryResult<NoInfer<TData>, TError>;
24+
>(
25+
options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,
26+
): DistributivePick<UseQueryResult<NoInfer<TData>, TError>, CommonQueryResult>;
2427

2528
export function useClerkQuery<
2629
TQueryFnData = unknown,
2730
TError = DefaultError,
2831
TData = TQueryFnData,
2932
TQueryKey extends QueryKey = QueryKey,
30-
>(options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>): UseQueryResult<NoInfer<TData>, TError>;
33+
>(
34+
options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
35+
): DistributivePick<UseQueryResult<NoInfer<TData>, TError>, CommonQueryResult>;
3136

3237
/**
3338
*

packages/shared/src/react/hooks/useSubscription.rq.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export function useSubscription(params?: UseSubscriptionParams): SubscriptionRes
3636
? environment?.commerceSettings.billing.organization.enabled
3737
: environment?.commerceSettings.billing.user.enabled;
3838

39-
const queryClient = useClerkQueryClient();
39+
const [queryClient] = useClerkQueryClient();
4040

4141
const queryKey = useMemo(() => {
4242
return [
@@ -55,7 +55,7 @@ export function useSubscription(params?: UseSubscriptionParams): SubscriptionRes
5555
return clerk.billing.getSubscription(obj.args);
5656
},
5757
staleTime: 1_000 * 60,
58-
enabled: Boolean(user?.id && billingEnabled),
58+
enabled: Boolean(user?.id && billingEnabled) && ((params as any)?.enabled ?? true),
5959
});
6060

6161
const revalidate = useCallback(() => queryClient.invalidateQueries({ queryKey }), [queryClient, queryKey]);
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import type { PropsWithChildren } from 'react';
22
import React from 'react';
3+
import { SWRConfig } from 'swr';
34

45
/**
56
* @internal
67
*/
7-
export function SWRConfigCompat({ children }: PropsWithChildren) {
8-
return <>{children}</>;
8+
export function SWRConfigCompat({ swrConfig, children }: PropsWithChildren<{ swrConfig?: any }>) {
9+
return <SWRConfig value={swrConfig}>{children}</SWRConfig>;
910
}

0 commit comments

Comments
 (0)