-
-
Notifications
You must be signed in to change notification settings - Fork 128
feat(react-swr): React SWR Integration #891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
b9fc448
init
unnoq 603a7e9
wip
unnoq 2f614a0
improve
unnoq 3bb6c8e
e2e tests
unnoq 0e078d9
docs + operation context
unnoq 871f2e4
refetchMode
unnoq 4d6ad32
Merge branch 'main' into feat/react-swr/integration
unnoq 7569bb8
improve tests
unnoq cefd426
README
unnoq 39de620
jsdoc
unnoq 9abeda1
Merge branch 'main' into feat/react-swr/integration
unnoq 7360b73
improve
unnoq aa4e948
improve
unnoq File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| --- | ||
| title: React SWR Integration | ||
| description: Integrate oRPC with React SWR for efficient data fetching and caching. | ||
| --- | ||
|
|
||
| # React SWR Integration | ||
|
|
||
| [SWR](https://swr.vercel.app/) 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](https://swr.vercel.app/). If you need a refresher, please review the official SWR documentation before proceeding. | ||
| ::: | ||
|
|
||
| ## Installation | ||
|
|
||
| ::: code-group | ||
|
|
||
| ```sh [npm] | ||
| npm install @orpc/experimental-react-swr@latest | ||
| ``` | ||
|
|
||
| ```sh [yarn] | ||
| yarn add @orpc/experimental-react-swr@latest | ||
| ``` | ||
|
|
||
| ```sh [pnpm] | ||
| pnpm add @orpc/experimental-react-swr@latest | ||
| ``` | ||
|
|
||
| ```sh [bun] | ||
| bun add @orpc/experimental-react-swr@latest | ||
| ``` | ||
|
|
||
| ```sh [deno] | ||
| 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. | ||
unnoq marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ::: | ||
|
|
||
| ## Setup | ||
|
|
||
| Before you begin, ensure you have already configured a [server-side client](/docs/client/server-side) or a [client-side client](/docs/client/client-side). | ||
|
|
||
| ```ts twoslash | ||
| import { router } from './shared/planet' | ||
| import { RouterClient } from '@orpc/server' | ||
|
|
||
| declare const client: RouterClient<typeof router> | ||
| // ---cut--- | ||
| import { createSWRUtils } from '@orpc/experimental-react-swr' | ||
|
|
||
| export const orpc = createSWRUtils(client) | ||
|
|
||
| orpc.planet.find.key({ input: { id: 123 } }) | ||
| // ^| | ||
|
|
||
| // | ||
|
|
||
| // | ||
|
|
||
| // | ||
|
|
||
| // | ||
| ``` | ||
|
|
||
| ::: details Avoiding Key Conflicts? | ||
|
|
||
| You can easily avoid key conflicts by passing a unique base key when creating your utils: | ||
|
|
||
| ```ts | ||
| 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: | ||
|
|
||
| ```ts | ||
| 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: | ||
|
|
||
| ```ts | ||
| 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](/docs/event-iterator): | ||
|
|
||
| ```ts | ||
| 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: | ||
|
|
||
| ```ts | ||
| 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: | ||
|
|
||
| ```ts | ||
| 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: | ||
|
|
||
| ```ts | ||
| 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. | ||
|
|
||
unnoq marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ```ts | ||
| 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](/docs/client/rpc-link#using-client-context). This context can be used to configure the request behavior, like setting the HTTP method. | ||
|
|
||
| ```ts | ||
| 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' | ||
| }, | ||
| }) | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.