Skip to main content
@orpc/svelte-query provides Svelte-specific utilities for TanStack Query, wrapping @tanstack/svelte-query so that createQuery, createInfiniteQuery, and createMutation receive fully typed options generated from your oRPC client.

Installation

npm install @orpc/svelte-query @tanstack/svelte-query

Setup

1

Create your oRPC client

import { createORPCClient } from '@orpc/client'
import { RPCLink } from '@orpc/client/fetch'
import type { RouterClient } from '@orpc/server'
import type { router } from './server'

const link = new RPCLink({ url: '/rpc' })
export const orpc: RouterClient<typeof router> = createORPCClient(link)
2

Create Svelte Query utils

import { createORPCSvelteQueryUtils } from '@orpc/svelte-query'
import { orpc } from './client'

export const orpcUtils = createORPCSvelteQueryUtils(orpc)
3

Set up QueryClient in your root layout

<!-- +layout.svelte -->
<script lang="ts">
  import { QueryClient, QueryClientProvider } from '@tanstack/svelte-query'

  const queryClient = new QueryClient()
</script>

<QueryClientProvider client={queryClient}>
  <slot />
</QueryClientProvider>

createQuery

<script lang="ts">
  import { createQuery } from '@tanstack/svelte-query'
  import { orpcUtils } from './orpc'

  const query = createQuery(
    orpcUtils.planet.list.queryOptions({ input: { limit: 10 } }),
  )
</script>

{#if $query.isLoading}
  <p>Loading...</p>
{:else if $query.error}
  <p>Error: {$query.error.message}</p>
{:else}
  <ul>
    {#each $query.data ?? [] as planet (planet.id)}
      <li>{planet.name}</li>
    {/each}
  </ul>
{/if}

createInfiniteQuery

<script lang="ts">
  import { createInfiniteQuery } from '@tanstack/svelte-query'
  import { orpcUtils } from './orpc'

  const query = createInfiniteQuery(
    orpcUtils.planet.list.infiniteOptions({
      input: pageParam => ({ cursor: pageParam, limit: 10 }),
      initialPageParam: 0,
      getNextPageParam: lastPage => lastPage.nextCursor,
    }),
  )
</script>

{#each $query.data?.pages.flat() ?? [] as planet (planet.id)}
  <div>{planet.name}</div>
{/each}

<button
  on:click={() => $query.fetchNextPage()}
  disabled={!$query.hasNextPage}
>
  Load more
</button>

createMutation

<script lang="ts">
  import { createMutation, useQueryClient } from '@tanstack/svelte-query'
  import { orpcUtils } from './orpc'

  const queryClient = useQueryClient()

  const mutation = createMutation(
    orpcUtils.planet.create.mutationOptions({
      onSuccess: async () => {
        await queryClient.invalidateQueries({
          queryKey: orpcUtils.planet.list.queryKey(),
        })
      },
    }),
  )
</script>

<button
  on:click={() => $mutation.mutate({ name: 'Mars' })}
  disabled={$mutation.isPending}
>
  Create planet
</button>

Cache invalidation

const queryClient = useQueryClient()

// Invalidate a specific query
await queryClient.invalidateQueries({
  queryKey: orpcUtils.planet.list.queryKey(),
})

// Invalidate all planet queries
await queryClient.invalidateQueries({
  queryKey: orpcUtils.planet.key(),
})

Build docs developers (and LLMs) love