Skip to main content
@orpc/solid-query provides SolidJS-specific utilities for TanStack Query, wrapping @tanstack/solid-query types so that createQuery, createInfiniteQuery, and createMutation receive fully typed options.

Installation

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

Setup

1

Wrap your app with QueryClientProvider

import { QueryClient, QueryClientProvider } from '@tanstack/solid-query'

const queryClient = new QueryClient()

export function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <YourApp />
    </QueryClientProvider>
  )
}
2

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)
3

Create Solid Query utils

import { createORPCSolidQueryUtils } from '@orpc/solid-query'
import { orpc } from './client'

export const orpcUtils = createORPCSolidQueryUtils(orpc)

createQuery

import { createQuery } from '@tanstack/solid-query'
import { orpcUtils } from './orpc'

export function PlanetList() {
  const query = createQuery(() =>
    orpcUtils.planet.list.queryOptions({ input: { limit: 10 } }),
  )

  return (
    <div>
      <Show when={query.isLoading}>Loading...</Show>
      <Show when={query.error}>{query.error?.message}</Show>
      <For each={query.data}>
        {planet => <div>{planet.name}</div>}
      </For>
    </div>
  )
}
In SolidJS, createQuery (and the other hooks) accept a reactive accessor function () => options. Pass a function that returns the result of queryOptions() so that the query is reactive.

createInfiniteQuery

import { createInfiniteQuery } from '@tanstack/solid-query'
import { orpcUtils } from './orpc'

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

  return (
    <div>
      <For each={query.data?.pages.flat()}>
        {planet => <div>{planet.name}</div>}
      </For>
      <button onClick={() => query.fetchNextPage()} disabled={!query.hasNextPage}>
        Load more
      </button>
    </div>
  )
}

createMutation

import { createMutation, useQueryClient } from '@tanstack/solid-query'
import { orpcUtils } from './orpc'

export function CreatePlanetButton() {
  const queryClient = useQueryClient()

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

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

Cache invalidation

const queryClient = useQueryClient()

await queryClient.invalidateQueries({
  queryKey: orpcUtils.planet.list.queryKey(),
})

await queryClient.invalidateQueries({
  queryKey: orpcUtils.planet.key(),
})

Build docs developers (and LLMs) love