trpc-svelte-query Svelte Themes

Trpc Svelte Query

tRPC

trpc-svelte-query

Type-safe svelte(kit) tRPC integration with @tanstack/svelte-query

Contents

Installation

pnpm i trpc-svelte-query @tanstack/svelte-query

Basic Example

Set up tRPC in lib/trpc/index.ts

// Import the router type from your server file
import type { AppRouter } from '$lib/server/routes/_app';
import { createTRPCSvelte, httpBatchLink } from 'trpc-svelte-query';

export const trpc = createTRPCSvelte<AppRouter>({
    links: [
        httpBatchLink({
            url: '/api/trpc',
        }),
    ],
});

Set up @tanstack/svelte-query's provider in your root layout.

<script lang="ts">
  import { QueryClientProvider } from '@tanstack/svelte-query';
  import { trpc } from '$lib/trpc/client';

    const { children } = $props();
</script>

<QueryClientProvider client={trpc.queryClient}>
  {@render children?.()}
</QueryClientProvider>

Set up your API handler in routes/api/trpc/[...trpc]/+server.ts

import { appRouter } from '$lib/server/routes/_app';
import { createTRPCSvelteServer } from 'trpc-svelte-query/server';

const trpcServer = createTRPCSvelteServer({
    endpoint: '/api/trpc',
    router: appRouter,
});

export const GET = trpcServer.handler;
export const POST = trpcServer.handler;

Now in any component, you can query your API using the client you created.

<script lang="ts">
  import { trpc } from '$lib/trpc/client';

  const query = trpc.greeting.query({ name: 'tRPC' });
</script>

{#if $query.isSuccess}
  <p>{$query.data.greeting}</p>
{:else if $query.isError}
  <p>{$query.error.message}</p>
{:else}
  <p>Loading...</p>
{/if}

SSR with SvelteKit

Extract your trpcServer instance into its own file (i.e. $lib/server/server). You'll use this object to handle SSR.

import { appRouter } from '$lib/server/routes/_app';
import { createTRPCSvelteServer } from 'trpc-svelte-query/server';

export const trpcServer = createTRPCSvelteServer({
    endpoint: '/api/trpc',
    router: appRouter,
});

Use that instance in your api endpoint:

import { trpcServer } from '$lib/server/server';

export const GET = trpcServer.handler;
export const POST = trpcServer.handler;

Add a root +layout.server.ts to pass SSR data from the server to the client.

import { trpcServer } from '$lib/server/server';

export const load = async (event) => {
    return {
        trpc: trpcServer.hydrateToClient(event),
    };
};

Update your root layout to hydrate that SSR data.

<script lang="ts">
  import { trpc } from '$lib/trpc/client';

    const { data, children } = $props();

  trpc.hydrateFromServer(() => data.trpc);
</script>

{@render children?.()}

Add a +page.server.ts file to preload specific queries.

import { trpc } from '$lib/server/server';

export const load = async () => {
    await trpcServer.greeting.ssr({ name: 'tRPC' });
};

Migrating from v2

  • Update tRPC to v11 (migration guide)
  • Update SvelteKit to at least 2.20.0
  • Remove QueryClientProvider if using SSR:
 +layout.svelte:

<script lang="ts">
-  import { QueryClientProvider } from '@tanstack/svelte-query';

  import { trpc } from '$lib/trpc/client';

  const { data, children } = $props();

-  const queryClient = trpc.hydrateFromServer(data.trpc);
+  trpc.hydrateFromServer(() => data.trpc);
</script>

- <QueryClientProvider client={queryClient}>
{@render children?.()}
- </QueryClientProvider>
  • Don't pass event into SSR functions:
import { trpc } from '$lib/server/server';

export const load = async () => {
-  await trpcServer.greeting.ssr({ name: 'tRPC' }, event);
+  await trpcServer.greeting.ssr({ name: 'tRPC' });
};

Top categories

Loading Svelte Themes