Calling procedures
Learn how to call queries and mutations in your app.
Overview
There are two ways to call procedures. In client components we use the
useQuery, 'useSuspenseQuery' and useMutation hooks to call the procedures.
On the server we use the trpc api caller to call the procedures directly.
Client
The client uses Tanstack Query to manage data fetching and caching.
useQuery
'use client'
import { useQuery } from '@tanstack/react-query'
import { useTRPC } from '#lib/trpc/react'
export function ContactPage(props: {
params: {
id: string
}
}) {
const trpc = useTRPC()
const { data, isLoading } = useQuery(
trpc.contacts.byId.queryOptions({
id: props.params.id,
}),
)
// render the page
}useSuspenseQuery
useSuspenseQuery is very useful as it guarantees data to be defined, so you
don't have to check for isLoading for conditional rendering. It also enables
you use Next.js streaming to render the page as soon as the data is available.
// in a server component, eg page or layout
import { Suspense } from 'react'
import { ContactPage } from '#components/contact-page'
import { HydrateClient, prefetch, trpc } from '#lib/trpc/rsc'
export default async function Page(params: { id: string }) {
prefetch(
trpc.contacts.byId.queryOptions({
id: params.id,
}),
)
return (
<HydrateClient>
<Suspense fallback={<div>Loading...</div>}>
<ContactPage id={params.id} />
</Suspense>
</HydrateClient>
)
}// in a client component
import { useTRPC } from '#lib/trpc/react'
export function ContactPage(props: { id: string }) {
const trpc = useTRPC()
const { data } = useSuspenseQuery(
trpc.contacts.byId.queryOptions({
id,
}),
)
return <div>{data.name}</div>
}useMutation
'use client'
import { useAuth } from '@saas-ui/auth-provider'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useTRPC } from '#lib/trpc/react'
export default function ProfilePage() {
const { user } = useAuth()
const trpc = useTRPC()
const queryClient = useQueryClient()
const mutation = useMutation(
trpc.users.updateProfile.mutationOptions({
onSettled: () => {
// Invalidate the user cache, so the updated user is refetched
queryClient.invalidateQueries({
queryKey: trpc.users.updateProfile.queryKey(),
})
},
}),
)
return (
<button
onClick={() => {
mutation.mutate({
name: 'John Doe',
})
}}
>
Save
</button>
)
}Server
To fetch and use the data on the server, you can use the caller object.
// app/[slug]/layout.tsx
import { caller } from '#lib/trpc/rsc'
export default Layout(props: {
children: React.ReactNode
params: {
slug: string
}
}) {
const workspace = await caller.workspaces.bySlug({
slug: props.params.slug,
})
if (!workspace) {
notFound()
}
return (
<div>
{props.children}
</div>
)
}