Skip to content

Commit

Permalink
fix(react-query): make .createClient() be a typed client (trpc#6340)
Browse files Browse the repository at this point in the history
  • Loading branch information
KATT authored Dec 28, 2024
1 parent 449d763 commit 1032f48
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 31 deletions.
10 changes: 7 additions & 3 deletions packages/next/src/app-dir/shared.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type {
CreateTRPCClientOptions,
inferRouterClient,
Resolver,
TRPCUntypedClient,
} from '@trpc/client';
import { getUntypedClient, TRPCUntypedClient } from '@trpc/client';
import type { inferProcedureOutput } from '@trpc/server';
import type {
AnyClientTypes,
Expand Down Expand Up @@ -39,8 +40,11 @@ export type UseProcedureRecord<
};

export function createUseProxy<TRouter extends AnyRouter>(
client: TRPCUntypedClient<TRouter>,
client: TRPCUntypedClient<TRouter> | inferRouterClient<TRouter>,
) {
const untypedClient: TRPCUntypedClient<TRouter> =
client instanceof TRPCUntypedClient ? client : getUntypedClient(client);

return createRecursiveProxy<
UseProcedureRecord<
TRouter['_def']['_config']['$types'],
Expand All @@ -49,7 +53,7 @@ export function createUseProxy<TRouter extends AnyRouter>(
>((opts) => {
const path = opts.path.join('.');

return client.query(path, ...opts.args);
return untypedClient.query(path, ...opts.args);
});
}

Expand Down
8 changes: 6 additions & 2 deletions packages/next/src/withTRPC.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
*/
import type { DehydratedState, QueryClient } from '@tanstack/react-query';
import { HydrationBoundary, QueryClientProvider } from '@tanstack/react-query';
import type { CreateTRPCClientOptions, TRPCUntypedClient } from '@trpc/client';
import type {
CreateTRPCClientOptions,
inferRouterClient,
TRPCUntypedClient,
} from '@trpc/client';
import type { CoercedTransformerParameters } from '@trpc/client/unstable-internals';
import {
getTransformer,
Expand Down Expand Up @@ -78,7 +82,7 @@ export type TRPCPrepassProps<
> = {
config: WithTRPCConfig<TRouter>;
queryClient: QueryClient;
trpcClient: TRPCUntypedClient<TRouter>;
trpcClient: TRPCUntypedClient<TRouter> | inferRouterClient<TRouter>;
ssrState: 'prepass';
ssrContext: TSSRContext;
};
Expand Down
5 changes: 2 additions & 3 deletions packages/react-query/src/createTRPCReact.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type {
UseSuspenseInfiniteQueryResult,
UseSuspenseQueryResult,
} from '@tanstack/react-query';
import type { TRPCClientErrorLike } from '@trpc/client';
import type { createTRPCClient, TRPCClientErrorLike } from '@trpc/client';
import type {
AnyProcedure,
AnyRootTypes,
Expand Down Expand Up @@ -38,7 +38,6 @@ import { createReactDecoration, createReactQueryUtils } from './shared';
import type { CreateReactQueryHooks } from './shared/hooks/createHooksInternal';
import { createRootHooks } from './shared/hooks/createHooksInternal';
import type {
CreateClient,
DefinedUseTRPCQueryOptions,
DefinedUseTRPCQueryResult,
TRPCHookResult,
Expand Down Expand Up @@ -469,7 +468,7 @@ export type CreateTRPCReactBase<TRouter extends AnyRouter, TSSRContext> = {
*/
useUtils(): CreateReactUtils<TRouter, TSSRContext>;
Provider: TRPCProvider<TRouter, TSSRContext>;
createClient: CreateClient<TRouter>;
createClient: typeof createTRPCClient<TRouter>;
useQueries: TRPCUseQueries<TRouter>;
useSuspenseQueries: TRPCUseSuspenseQueries<TRouter>;
};
Expand Down
18 changes: 12 additions & 6 deletions packages/react-query/src/shared/hooks/createHooksInternal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import {
skipToken,
} from '@tanstack/react-query';
import type { TRPCClientErrorLike } from '@trpc/client';
import { createTRPCUntypedClient } from '@trpc/client';
import {
createTRPCClient,
getUntypedClient,
TRPCUntypedClient,
} from '@trpc/client';
import type { AnyRouter } from '@trpc/server/unstable-core-do-not-import';
import { isAsyncIterable } from '@trpc/server/unstable-core-do-not-import';
import * as React from 'react';
Expand All @@ -36,7 +40,6 @@ import { createUtilityFunctions } from '../../utils/createUtilityFunctions';
import { createUseQueries } from '../proxy/useQueriesProxy';
import type { CreateTRPCReactOptions, UseMutationOverride } from '../types';
import type {
CreateClient,
TRPCProvider,
TRPCQueryOptions,
TRPCSubscriptionResult,
Expand Down Expand Up @@ -87,16 +90,19 @@ export function createRootHooks<
const Context = (config?.context ??
TRPCContext) as React.Context<ProviderContext>;

const createClient: CreateClient<TRouter> = (opts) => {
return createTRPCUntypedClient(opts);
};
const createClient = createTRPCClient<TRouter>;

const TRPCProvider: TRPCProvider<TRouter, TSSRContext> = (props) => {
const { abortOnUnmount = false, client, queryClient, ssrContext } = props;
const { abortOnUnmount = false, queryClient, ssrContext } = props;
const [ssrState, setSSRState] = React.useState<SSRState>(
props.ssrState ?? false,
);

const client: TRPCUntypedClient<TRouter> =
props.client instanceof TRPCUntypedClient
? props.client
: getUntypedClient(props.client);

const fns = React.useMemo(
() =>
createUtilityFunctions({
Expand Down
10 changes: 3 additions & 7 deletions packages/react-query/src/shared/hooks/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type {
DefinedUseQueryResult,
DehydratedState,
FetchInfiniteQueryOptions,
FetchQueryOptions,
InfiniteData,
Expand All @@ -21,6 +20,7 @@ import type {
} from '@tanstack/react-query';
import type {
CreateTRPCClientOptions,
inferRouterClient,
TRPCRequestOptions,
TRPCUntypedClient,
} from '@trpc/client';
Expand Down Expand Up @@ -226,19 +226,15 @@ export type TRPCSubscriptionResult<TOutput, TError> =
| TRPCSubscriptionPendingResult<TOutput>;

export interface TRPCProviderProps<TRouter extends AnyRouter, TSSRContext>
extends TRPCContextProps<TRouter, TSSRContext> {
extends Omit<TRPCContextProps<TRouter, TSSRContext>, 'client'> {
children: ReactNode;
client: inferRouterClient<TRouter> | TRPCUntypedClient<TRouter>;
}

export type TRPCProvider<TRouter extends AnyRouter, TSSRContext> = (
props: TRPCProviderProps<TRouter, TSSRContext>,
) => JSX.Element;

export type UseDehydratedState<TRouter extends AnyRouter> = (
client: TRPCUntypedClient<TRouter>,
trpcState: DehydratedState | undefined,
) => DehydratedState | undefined;

export type CreateClient<TRouter extends AnyRouter> = (
opts: CreateTRPCClientOptions<TRouter>,
) => TRPCUntypedClient<TRouter>;
Expand Down
14 changes: 11 additions & 3 deletions packages/react-query/src/shared/proxy/useQueriesProxy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type { QueryOptions } from '@tanstack/react-query';
import type { TRPCClientError, TRPCUntypedClient } from '@trpc/client';
import {
getUntypedClient,
TRPCUntypedClient,
type inferRouterClient,
type TRPCClientError,
} from '@trpc/client';
import type {
AnyProcedure,
AnyQueryProcedure,
Expand Down Expand Up @@ -86,8 +91,11 @@ export type UseSuspenseQueriesProcedureRecord<
* @internal
*/
export function createUseQueries<TRouter extends AnyRouter>(
client: TRPCUntypedClient<TRouter>,
client: TRPCUntypedClient<TRouter> | inferRouterClient<TRouter>,
) {
const untypedClient: TRPCUntypedClient<TRouter> =
client instanceof TRPCUntypedClient ? client : getUntypedClient(client);

return createRecursiveProxy<
UseQueriesProcedureRecord<
TRouter['_def']['_config']['$types'],
Expand All @@ -104,7 +112,7 @@ export function createUseQueries<TRouter extends AnyRouter>(
const options: QueryOptions = {
queryKey: getQueryKeyInternal(arrayPath, input, 'query'),
queryFn: () => {
return client.query(dotPath, input, _opts?.trpc);
return untypedClient.query(dotPath, input, _opts?.trpc);
},
..._opts,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import EventEmitter, { on } from 'events';
import { konn } from 'konn';
import { expect, vi } from 'vitest';
import { run } from '../../utils';
import { makeResource } from './disposable';
import { timerResource } from './timerResource';
import { withPing } from './withPing';

export interface MyEvents {
Expand Down
9 changes: 4 additions & 5 deletions www/docs/client/react/createTRPCQueryUtils.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ sidebar_label: createTRPCQueryUtils()
slug: /client/react/createTRPCQueryUtils
---

Similar to `useUtils`, `createTRPCQueryUtils` is a function that gives you access to helpers that let you manage the cached data of the queries you execute via `@trpc/react-query`. These helpers are actually thin wrappers around `@tanstack/react-query`'s [`queryClient`](https://tanstack.com/query/v5/docs/reference/QueryClient) methods. If you want more in-depth information about options and usage patterns for `useUtils` helpers than what we provide here, we will link to their respective `@tanstack/react-query` docs so you can refer to them accordingly.
The use case for `createTRPCQueryUtils` is when you need to use the helpers outside of a React Component, for example in `react-router`s loaders.

:::note
Similar to `useUtils`, `createTRPCQueryUtils` is a function that gives you access to helpers that let you manage the cached data of the queries you execute via `@trpc/react-query`. These helpers are actually thin wrappers around `@tanstack/react-query`'s [`queryClient`](https://tanstack.com/query/v5/docs/reference/QueryClient) methods. If you want more in-depth information about options and usage patterns for `useUtils` helpers than what we provide here, we will link to their respective `@tanstack/react-query` docs so you can refer to them accordingly.

The difference between `useUtils` and `createTRPCQueryUtils` is that `useUtils` is a react hook that uses `useQueryClient` under the hood. This means that it is able to work better within React Components.
The use case for `createTRPCQueryUtils` is when you need to use the helpers outside of a React Component, for example in react-router's loaders.

:::
If you need access to the client directly, you can use the `client` object that you passed to `createTRPCQueryUtils` during creation.

:::caution

Expand Down Expand Up @@ -100,4 +99,4 @@ If you were using Remix Run or SSR you wouldn't re-use the same `queryClient` fo

Much like `useUtils`, `createTRPCQueryUtils` gives you access to same set of helpers. The only difference is that you need to pass in the `queryClient` and `client` objects.

You can see them on the [useUtils](/docs/client/react/useUtils) page.
You can see them on the [useUtils](./useUtils.mdx#helpers)-page.

0 comments on commit 1032f48

Please sign in to comment.