添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
wleistra
wleistra 8mo ago

shared useTRPCClient hook conversion to v11

In our mono repo, we have 30 or so MFEs which all use the same TRPC client setup. So, we abstracted the inner workings of getting the TRPC client set up away in a different package as a hook. Now, I'm converting the code to v11, and I'm running into deprecation warnings and typescript errors. Our hook looks like this:
import { useState } from 'react';

import { createWSClient, getFetch, httpLink, splitLink, wsLink } from '@trpc/client';
import type { TRPCClient, TRPCLink } from '@trpc/client'; // [1] TRPCClient no longer exported

import type { AnyRouter } from '@trpc/server'; // [2] AnyRouter deprecated

type TRPC<TRouter extends AnyRouter> = {
createClient: (opts: { links: TRPCLink<TRouter>[] }) => TRPCClient<TRouter>;
};

export const useTRPCClient = <TRouter extends AnyRouter>(trpc: TRPC<TRouter>, url: string, wsUrl?: string) => {
const [trpcClient] = useState(() => {
const http = httpLink({
url,
fetch: async (input, init) => {
const fetch = getFetch();
return fetch(input, { ...init, credentials: 'include' });
},
headers: () => {
const originURL = window.location.href;
return {
'origin-url': originURL,
};
},
});

const wsClient = wsUrl ? createWSClient({ url: wsUrl }) : null;
const ws = wsClient ? wsLink({ client: wsClient }) : null;

return trpc.createClient({
links: ws
? [
splitLink({
condition: (op) => op.type === 'subscription',
true: ws,
false: http,
}),
]
: [http],
});
});

return trpcClient;
};
import { useState } from 'react';

import { createWSClient, getFetch, httpLink, splitLink, wsLink } from '@trpc/client';
import type { TRPCClient, TRPCLink } from '@trpc/client'; // [1] TRPCClient no longer exported

import type { AnyRouter } from '@trpc/server'; // [2] AnyRouter deprecated

type TRPC<TRouter extends AnyRouter> = {
createClient: (opts: { links: TRPCLink<TRouter>[] }) => TRPCClient<TRouter>;
};

export const useTRPCClient = <TRouter extends AnyRouter>(trpc: TRPC<TRouter>, url: string, wsUrl?: string) => {
const [trpcClient] = useState(() => {
const http = httpLink({
url,
fetch: async (input, init) => {
const fetch = getFetch();
return fetch(input, { ...init, credentials: 'include' });
},
headers: () => {
const originURL = window.location.href;
return {
'origin-url': originURL,
};
},
});

const wsClient = wsUrl ? createWSClient({ url: wsUrl }) : null;
const ws = wsClient ? wsLink({ client: wsClient }) : null;

return trpc.createClient({
links: ws
? [
splitLink({
condition: (op) => op.type === 'subscription',
true: ws,
false: http,
}),
]
: [http],
});
});

return trpcClient;
};
Issue 1: TRPCClient type is no longer exported from @trpc/client. I assume we can replace it with createClient: (opts: { links: TRPCLink<TRouter>[] }) => ReturnType<typeof createTRPCClient>; correct? Issue 2: the AnyRouter type deprecation, how can that be resolved?
6 Replies
BeBoRE
BeBoRE 8mo ago
Why not use @trpc/react ?
wleistra
wleistra 8mo ago
We do! The prop trpc is coming from createReactRouter<AppRouter> like this
import type { AppRouter } from 'mfe-middleware';

import type { inferReactQueryProcedureOptions } from '@trpc/react-query';
import { createTRPCReact } from '@trpc/react-query';
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';

/* eslint-disable import/no-unused-modules */
export type ReactQueryOptions = inferReactQueryProcedureOptions<AppRouter>;
export type RouterInputs = inferRouterInputs<AppRouter>;
export type RouterOutputs = inferRouterOutputs<AppRouter>;
/* eslint-enable import/no-unused-modules */

export const trpc = createTRPCReact<AppRouter>();
import type { AppRouter } from 'mfe-middleware';

import type { inferReactQueryProcedureOptions } from '@trpc/react-query';
import { createTRPCReact } from '@trpc/react-query';
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';

/* eslint-disable import/no-unused-modules */
export type ReactQueryOptions = inferReactQueryProcedureOptions<AppRouter>;
export type RouterInputs = inferRouterInputs<AppRouter>;
export type RouterOutputs = inferRouterOutputs<AppRouter>;
/* eslint-enable import/no-unused-modules */

export const trpc = createTRPCReact<AppRouter>();
And this is how we put it all together
import type { ReactNode } from 'react';
import React from 'react';

import { createQueryClient, useTRPCClient } from '@company/utils';
import { QueryClientProvider } from '@tanstack/react-query';

import { trpc } from './trpc';

const queryClient = createQueryClient();

interface MFEQueryProviderProps {
children: ReactNode;
}

export const MFEQueryProvider = ({ children }: MFEQueryProviderProps) => {
const trpcClient = useTRPCClient(trpc, process.env.API_URL ?? '');

return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</trpc.Provider>
);
};
import type { ReactNode } from 'react';
import React from 'react';

import { createQueryClient, useTRPCClient } from '@company/utils';
import { QueryClientProvider } from '@tanstack/react-query';

import { trpc } from './trpc';

const queryClient = createQueryClient();

interface MFEQueryProviderProps {
children: ReactNode;
}

export const MFEQueryProvider = ({ children }: MFEQueryProviderProps) => {
const trpcClient = useTRPCClient(trpc, process.env.API_URL ?? '');

return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</trpc.Provider>
);
};
If there is a more efficient/better practice to achieve the sharing of the same client setup across all our Frontends without duplicating the code I'm all ears too... So far we successfully used this way with trpc 10
Alex / KATT 🐱
Alex / KATT 🐱 8mo ago
there should be comments on all deprecations feel free to make a pr on things that we might've removed we have started being explicit about what we import + added smurfing( https://blog.codinghorror.com/new-programming-jargon/#21 ) on most variables/types if you need consulting for the migration email you can email [email protected]
wleistra
wleistra 8mo ago
This is the information vscode gives about the deprecation: