React SWR Integration
SWR is a React Hooks library for data fetching that provides features like caching, revalidation, and more. oRPC SWR integration is very lightweight and straightforward - there's no extra overhead.
WARNING
This documentation assumes you are already familiar with SWR. If you need a refresher, please review the official SWR documentation before proceeding.
Installation
npm install @orpc/experimental-react-swr@latest
yarn add @orpc/experimental-react-swr@latest
pnpm add @orpc/experimental-react-swr@latest
bun add @orpc/experimental-react-swr@latest
deno install npm:@orpc/experimental-react-swr@latest
WARNING
The experimental-
prefix indicates that this integration is still in development and may change in the future.
Setup
Before you begin, ensure you have already configured a server-side client or a client-side client.
import { createSWRUtils } from '@orpc/experimental-react-swr'
export const orpc = createSWRUtils(client)
orpc.planet.find.key({ input: { id: 123 } })
//
//
//
//
Avoiding Key Conflicts?
You can easily avoid key conflicts by passing a unique base key when creating your utils:
const userORPC = createSWRUtils(userClient, {
path: ['user']
})
const postORPC = createSWRUtils(postClient, {
path: ['post']
})
Data Fetching
Use .key
and .fetcher
methods to configure useSWR
for data fetching:
import useSWR from 'swr'
const { data, error, isLoading } = useSWR(
orpc.planet.find.key({ input: { id: 123 } }),
orpc.planet.find.fetcher({ context: { cache: true } }), // Provide client context if needed
)
Infinite Queries
Use .key
and .fetcher
methods to configure useSWRInfinite
for infinite queries:
import useSWRInfinite from 'swr/infinite'
const { data, error, isLoading, size, setSize } = useSWRInfinite(
(index, previousPageData) => {
if (previousPageData && !previousPageData.nextCursor) {
return null // reached the end
}
return orpc.planet.list.key({ input: { cursor: previousPageData?.nextCursor } })
},
orpc.planet.list.fetcher({ context: { cache: true } }), // Provide client context if needed
)
Subscriptions
Use .key
and .subscriber
methods to configure useSWRSubscription
to subscribe to an Event Iterator:
import useSWRSubscription from 'swr/subscription'
const { data, error } = useSWRSubscription(
orpc.streamed.key({ input: { id: 3 } }),
orpc.streamed.subscriber({ context: { cache: true }, maxChunks: 10 }), // Provide client context if needed
)
Use .liveSubscriber
to subscribe to the latest events without chunking:
import useSWRSubscription from 'swr/subscription'
const { data, error } = useSWRSubscription(
orpc.streamed.key({ input: { id: 3 } }),
orpc.streamed.liveSubscriber({ context: { cache: true } }), // Provide client context if needed
)
Mutations
Use .key
and .mutator
methods to configure useSWRMutation
for mutations with automatic revalidation on success:
import useSWRMutation from 'swr/mutation'
const { trigger, isMutating } = useSWRMutation(
orpc.planet.list.key(),
orpc.planet.create.mutator({ context: { cache: true } }), // Provide client context if needed
)
trigger({ name: 'New Planet' }) // auto revalidate orpc.planet.list.key() on success
Manual Revalidation
Use .matcher
to invalidate data manually:
import { mutate } from 'swr'
mutate(orpc.matcher()) // invalidate all orpc data
mutate(orpc.planet.matcher()) // invalidate all planet data
mutate(orpc.planet.find.matcher({ input: { id: 123 }, strategy: 'exact' })) // invalidate specific planet data
Calling Clients
Use .call
to call a procedure client directly. It's an alias for corresponding procedure client.
const planet = await orpc.planet.find.call({ id: 123 })
Operation Context
When clients are invoked through the SWR integration, an operation context is automatically added to the client context. This context can be used to configure the request behavior, like setting the HTTP method.
import {
SWR_OPERATION_CONTEXT_SYMBOL,
SWROperationContext,
} from '@orpc/experimental-react-swr'
interface ClientContext extends SWROperationContext {
}
const GET_OPERATION_TYPE = new Set(['fetcher', 'subscriber', 'liveSubscriber'])
const link = new RPCLink<ClientContext>({
url: 'http://localhost:3000/rpc',
method: ({ context }, path) => {
const operationType = context[SWR_OPERATION_CONTEXT_SYMBOL]?.type
if (operationType && GET_OPERATION_TYPE.has(operationType)) {
return 'GET'
}
return 'POST'
},
})