Skip to content
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

feat(react-query): next-app-router example with prefetch helpers #5451

Merged
merged 123 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
123 commits
Select commit Hold shift + click to select a range
70a0c71
next-app-router example with prefetch helpers
juliusmarminge Feb 6, 2024
fd05259
chore: apply lint and formatting fixes
autofix-ci[bot] Feb 6, 2024
e8e3c8d
<Posts/>
juliusmarminge Feb 6, 2024
04bb3b9
commity env
juliusmarminge Feb 6, 2024
18df440
readme
juliusmarminge Feb 6, 2024
1375467
why did autofixer do thsi?
juliusmarminge Feb 6, 2024
5b5f71e
fix manypkg things...
juliusmarminge Feb 6, 2024
82d4d85
Merge branch 'next' into app-router-example
juliusmarminge Feb 7, 2024
9d7762a
chore: apply lint and formatting fixes
autofix-ci[bot] Feb 7, 2024
e9fe669
Merge branch 'next' into app-router-example
juliusmarminge Feb 8, 2024
efa894c
wtf linter???
juliusmarminge Feb 8, 2024
40ea132
no infer
juliusmarminge Feb 8, 2024
ad941c8
Merge branch 'next' into app-router-example
juliusmarminge Feb 8, 2024
1b2ea2d
skip this autolinter thing
juliusmarminge Feb 8, 2024
bbeaea4
Merge branch 'next' into app-router-example
juliusmarminge Mar 4, 2024
42d96f5
Merge branch 'next' into app-router-example
juliusmarminge Mar 7, 2024
45a9eb5
up
juliusmarminge Mar 7, 2024
b729b2b
wait query with nested suspense
juliusmarminge Mar 7, 2024
97c049d
docs: update batching toggle docs (#5553)
KATT Mar 8, 2024
9e26b44
fix(server + client): skip referencing `NodeJS.*` (#5562)
KATT Mar 11, 2024
0175098
fix: Export required types for TypeScript workspaces (#5500)
jeffberry Mar 11, 2024
dde5e8b
fix(example): custom websocket server not upgrading due to next 13.4.…
dougkulak Mar 12, 2024
5eadbc7
chore: make dependabot understand bumps in `next`-tag (#5578)
KATT Mar 22, 2024
3be4c5a
chore: bump pnpm (#5579)
KATT Mar 22, 2024
cf27db6
feat(server): add `experimental_caller()` (#5584)
KATT Mar 26, 2024
c36d09f
feat(server): add an `onError`-option to router caller (#5585)
KATT Mar 26, 2024
bba3f97
feat(next app dir): rethrow built-in Next errors (#5587)
KATT Mar 26, 2024
bf5ce50
feat(server): add next.js `experimental_caller()`-adapter (#5589)
KATT Mar 27, 2024
b9b3610
return redirect (#5593)
juliusmarminge Mar 27, 2024
db93230
patch(server): bump `@fastify/websocket` to 10.0.1 (#5592)
vafanassieff Mar 27, 2024
3067e25
chore(docs): Update setup.mdx (#5594)
KATT Mar 27, 2024
143bfaa
feat: release v11 release candidate (#5601)
KATT Mar 30, 2024
5c009f9
patch(server): fix `dev --turbo` (#5604)
KATT Apr 2, 2024
50959e1
fix(deps): update dependency eslint-plugin-unicorn to v52 (#5608)
renovate[bot] Apr 3, 2024
375abc3
fix(react-query): use `optsRef` in `useSubscription` (#5610)
KATT Apr 4, 2024
683e592
fix(deps): update dependency @testing-library/dom to v10 (#5617)
renovate[bot] Apr 8, 2024
86dd51d
fix(server): remove extra export for router (#5621)
ax-at Apr 9, 2024
af1a832
docs: Add Ethereum DApp example (#5615)
tr1sm0s1n Apr 9, 2024
7fd3e2e
fix(deps): update dependency @testing-library/react to v15 (#5624)
renovate[bot] Apr 10, 2024
550563e
chore(deps): Remove unused dependency aws-lambda (#5628)
astuyve Apr 13, 2024
c61de82
chore: make sure test job runs on pushes (#5630)
KATT Apr 13, 2024
c48eb0a
chore: fix codecov (#5631)
KATT Apr 13, 2024
fbf388a
patch(client): createInnerProxy exclude apply bind and call (#5629)
KATT Apr 13, 2024
4e9ca0a
chore: bump prisma (#5632)
KATT Apr 13, 2024
aa0d06d
feat: export procedure types (#5640)
infodusha Apr 19, 2024
7bb86bb
chore: remove `name:` from jobs in ci (#5641)
KATT Apr 19, 2024
f418809
fix(deps): update dependency devalue to v5 (#5646)
renovate[bot] Apr 19, 2024
854353d
feat: Support Content Types other than JSON (FormData, File, Blob, Ui…
Nick-Lucas Apr 20, 2024
235787b
fix: dump complex formdata stuff in favor of "using the platform" (#5…
juliusmarminge Apr 20, 2024
1769441
chore: better error for mismatched content-type (#5654)
juliusmarminge Apr 21, 2024
2a81b34
feat(react-query): expose `setQueriesData` in `useUtils` (#5605)
nabeelvalley Apr 21, 2024
1b66b3f
Update migrate-from-v10-to-v11.mdx (#5655)
KATT Apr 21, 2024
be7d3f0
Update migrate-from-v10-to-v11.mdx (#5656)
KATT Apr 21, 2024
e36bbae
fix: rollback formdata/octet type stream support (#5661)
KATT Apr 21, 2024
f5b8246
feat: add trpc-rabbitmq & trpc-mqtt to the awesome-trpc list (#5664)
edorgeville Apr 24, 2024
74cb83d
fix(deps): update dependency cssnano to v7 (#5669)
renovate[bot] Apr 25, 2024
c060eb2
feat(server): export `TRPCBuilder` class from `@trpc/server` package …
opiation Apr 25, 2024
8a63dd1
chore: bump react version (#5680)
KATT Apr 27, 2024
935cc8b
chore: add secret to codecov (#5633)
KATT Apr 28, 2024
4ff00b3
chore: fix codecov badge (#5689)
KATT Apr 28, 2024
0b9f580
chore: fix codecov for forks (#5688)
KATT Apr 28, 2024
634775a
feat(react-query): add support for global onSuccess for mutation (#5668)
tomer-yechiel Apr 28, 2024
2b3f2c3
docs: fix link to the react query integration page (#5693)
fpetrakov Apr 30, 2024
5fe9779
feat: add formdata and octet stream support (#5665)
Nick-Lucas Apr 30, 2024
ab18070
chore(server): rewrite `resolveHTTPResponse` with Fetch (#5684)
KATT Apr 30, 2024
5bd12e0
chore: tweak some comments (#5694)
KATT Apr 30, 2024
c67c598
chore: trigger subtree after release (#5695)
KATT Apr 30, 2024
f3e31b2
fix(deps): update dependency @headlessui/react to v2 (#5706)
renovate[bot] May 6, 2024
f9af5c3
chore(server): use `Readable.fromWeb()` to pipe responses (#5701)
KATT May 7, 2024
bfd5f2e
fix(deps): update dependency eslint-plugin-unicorn to v53 (#5712)
renovate[bot] May 10, 2024
05af9e4
chore: bump react (#5720)
KATT May 13, 2024
b35c918
feat(client): add `'none'` color option to default logger, add `withC…
jonluca May 14, 2024
d66a1d7
feat(server): websocket keep alive (#5715)
buraktt May 14, 2024
a43a348
Fixes a single typo in docs (#5716)
babakfp May 14, 2024
0784b4b
docs: add used by google (#5722)
KATT May 15, 2024
3a3bc2e
fix(server): handle large POST bodies in node-http (#5724)
jcarrus May 16, 2024
9bd66a4
feat(server + client): streaming mutations and queries over HTTP (#5700)
KATT May 19, 2024
1c0fc79
Add trpc-cli to awesome-trpc (#5733)
mmkal May 23, 2024
e01b7d5
docs: update aws-lambda.md (#5740)
KATT May 25, 2024
81d5810
Merge branch 'next' into app-router-example
juliusmarminge May 25, 2024
f8455e7
rev
juliusmarminge May 25, 2024
97340c3
updates
juliusmarminge May 25, 2024
1c4916e
rm dep
juliusmarminge May 25, 2024
3e31afb
try getting stream provider working
juliusmarminge May 26, 2024
0198a3e
Merge branch 'next' into app-router-example
juliusmarminge May 26, 2024
b515336
chore: apply lint and formatting fixes
autofix-ci[bot] May 26, 2024
ffa4e27
this'd be neat
juliusmarminge May 27, 2024
88aae3e
okayyy
juliusmarminge May 27, 2024
d0fd6d5
nicee
juliusmarminge May 27, 2024
857c383
Merge branch 'next' into app-router-example
juliusmarminge May 27, 2024
c11abdf
rm prefetchquery hoc
juliusmarminge May 27, 2024
37762c3
rethrow
juliusmarminge May 27, 2024
86545ce
reset lock
juliusmarminge May 27, 2024
1ee8428
revert autofixed stuff...
juliusmarminge May 27, 2024
f10c6f7
chore: apply lint and formatting fixes
autofix-ci[bot] May 27, 2024
1fc24fe
disable autofixer
juliusmarminge May 27, 2024
4d068ac
release tmp
juliusmarminge May 27, 2024
895b718
Merge branch 'next' into app-router-example
juliusmarminge Jun 2, 2024
59cdcc8
clarify comments
juliusmarminge Jun 2, 2024
bc87f07
fix bad import paths
juliusmarminge Jun 2, 2024
d4ee6d9
merge
juliusmarminge Jun 2, 2024
840e186
hmm
juliusmarminge Jun 2, 2024
4e17306
Merge branch 'next' into app-router-example
juliusmarminge Jun 8, 2024
a81c961
rm example in favor of current
juliusmarminge Jun 8, 2024
cd2b8e9
revert
juliusmarminge Jun 8, 2024
0e27e9f
sync lock
juliusmarminge Jun 8, 2024
6e3efa6
use shared getter
juliusmarminge Jun 8, 2024
67aecc1
dynammic
juliusmarminge Jun 8, 2024
1ca7af8
fix build
juliusmarminge Jun 8, 2024
a807f80
tsprune
juliusmarminge Jun 8, 2024
3af8013
fix link
juliusmarminge Jun 8, 2024
76c56f4
update link in test
juliusmarminge Jun 8, 2024
bc33899
test
juliusmarminge Jun 8, 2024
67d2544
improve test accuracy
juliusmarminge Jun 8, 2024
c359a47
rm
juliusmarminge Jun 8, 2024
882a6dd
data transforming
juliusmarminge Jun 8, 2024
28243c3
niceee
juliusmarminge Jun 8, 2024
18be748
superjson
juliusmarminge Jun 9, 2024
3b987a5
Merge branch 'next' into app-router-example
juliusmarminge Jun 9, 2024
ada86cc
Merge branch 'next' into app-router-example
juliusmarminge Jun 12, 2024
2b04d65
bump tsq
juliusmarminge Jun 12, 2024
77c47e7
transformer.deserialize
juliusmarminge Jun 12, 2024
cd5a683
clarfiy
juliusmarminge Jun 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ jobs:
# </autofixing>

# commit autofixes
- uses: autofix-ci/action@d3e591514b99d0fca6779455ff8338516663f7cc
if: ${{ failure() || success() }}
with:
commit-message: 'chore: apply lint and formatting fixes'
fail-fast: false
# - uses: autofix-ci/action@d3e591514b99d0fca6779455ff8338516663f7cc
# if: ${{ failure() || success() }}
# with:
# commit-message: 'chore: apply lint and formatting fixes'
# fail-fast: false
2 changes: 1 addition & 1 deletion .github/workflows/release-tmp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches:
# Replace this with the branch you want to release from
# 👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇
- 'rethrow-next-errors'
- 'app-router-example'
# 👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆
paths:
- '.github/workflows/release-tmp.yml'
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ dist/
.eslintcache
*.tsbuildinfo

db.sqlite

node_modules/
package-lock.json
yarn.lock
Expand Down
5 changes: 4 additions & 1 deletion examples/.experimental/next-app-dir/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
},
"dependencies": {
"@hookform/resolvers": "^2.9.11",
"@tanstack/react-query": "^5.25.0",
"@js-temporal/polyfill": "^0.4.4",
"@tanstack/react-query": "^5.45.0",
"@tanstack/react-query-devtools": "^5.45.0",
"@trpc/client": "npm:@trpc/client@next",
"@trpc/next": "npm:@trpc/next@next",
"@trpc/react-query": "npm:@trpc/react-query@next",
Expand All @@ -26,6 +28,7 @@
"react-dom": "^18.3.1",
"react-hook-form": "^7.43.3",
"react-hot-toast": "^2.4.1",
"server-only": "^0.0.1",
"superjson": "^1.12.4",
"trpc-api": "link:./src/trpc",
"typescript": "^5.4.0",
Expand Down
14 changes: 12 additions & 2 deletions examples/.experimental/next-app-dir/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,22 @@ export default async function Index() {
</li>
<li>
<Link
href="/rsc"
href="/rsc-links"
style={{
color: 'hsla(210, 16%, 80%, 1)',
}}
>
React Server Components
React Server Components with new tRPC Next.js Links
</Link>
</li>
<li>
<Link
href="/rsc-rq-prefetch"
style={{
color: 'hsla(210, 16%, 80%, 1)',
}}
>
RSC + React Query
</Link>
</li>
<li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default async function PostPage() {
<div style={{ display: 'flex', flexDirection: 'column' }}>
<span>Title: {latestPost.title}</span>
<span>Content: {latestPost.content}</span>
<span>Created At: {latestPost.createdAt.toISOString()}</span>
<span>Created At: {latestPost.createdAt.toLocaleString()}</span>
</div>
<form
style={{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { TRPCReactProvider } from '~/trpc/rq-client';

export default function Layout(props: Readonly<{ children: React.ReactNode }>) {
return <TRPCReactProvider>{props.children}</TRPCReactProvider>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { HydrateClient, trpc } from '~/trpc/rq-server';
import React from 'react';
import { Post } from './post';

export const dynamic = 'force-dynamic';

export default function Home() {
void trpc.getLatestPost.prefetch();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if a promise fails in a place like this?

is it safe / will node crash with "unhandled promise rejection"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

void will ignore errors?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the query will be retried when it mounts on the client depending on your retry options


return (
<main>
<h1>Latest Post</h1>
<HydrateClient>
<Post />
</HydrateClient>
</main>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use client';

import { trpc } from '~/trpc/rq-client';
import React from 'react';

export function Post() {
const utils = trpc.useUtils();
const [latestPost] = trpc.getLatestPost.useSuspenseQuery();

const { mutate: createPost } = trpc.createPost.useMutation({
onSuccess: async () => {
await utils.invalidate();
},
});

return (
<div>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<span>Title: {latestPost.title}</span>
<span>Content: {latestPost.content}</span>
<span>Created At: {latestPost.createdAt.toLocaleString()}</span>
</div>
<form
style={{
display: 'flex',
flexDirection: 'column',
gap: 8,
maxWidth: 300,
marginTop: 16,
}}
onSubmit={(e) => {
e.preventDefault();
const data = new FormData(e.target as HTMLFormElement);
createPost({
title: data.get('title') as string,
content: data.get('content') as string,
});
}}
>
<input name="title" placeholder="title" />
<input name="content" placeholder="content" />
<button type="submit">Create Post!</button>
</form>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Temporal } from '@js-temporal/polyfill';
import { z } from 'zod';
import { publicProcedure, router } from '../trpc';

let latestPost = {
id: 0,
title: 'latest post',
content: 'hello world',
createdAt: new Date(),
createdAt: Temporal.Now.plainDateTimeISO(),
};

export const createPost = publicProcedure
Expand All @@ -18,7 +19,7 @@ export const createPost = publicProcedure
.mutation(async (opts) => {
latestPost = {
id: latestPost.id + 1,
createdAt: new Date(),
createdAt: Temporal.Now.plainDateTimeISO(),
...opts.input,
};

Expand Down
10 changes: 8 additions & 2 deletions examples/.experimental/next-app-dir/src/server/trpc.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { experimental_createServerActionHandler } from '@trpc/next/app-dir/server';
import { initTRPC, TRPCError } from '@trpc/server';
import { auth } from '~/auth';
import { transformer } from '~/trpc/shared';
import { headers } from 'next/headers';
import superjson from 'superjson';
import { ZodError } from 'zod';
import type { Context } from './context';

const t = initTRPC.context<Context>().create({
transformer: superjson,
transformer,
errorFormatter(opts) {
const { shape, error } = opts;
return {
Expand All @@ -23,6 +23,12 @@ const t = initTRPC.context<Context>().create({
},
});

/**
* Create a server-side caller
* @see https://trpc.io/docs/server/server-side-calls
*/
export const createCallerFactory = t.createCallerFactory;

export const router = t.router;
export const publicProcedure = t.procedure;

Expand Down
7 changes: 3 additions & 4 deletions examples/.experimental/next-app-dir/src/trpc/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import {
} from '@trpc/next/app-dir/client';
import { experimental_nextHttpLink } from '@trpc/next/app-dir/links/nextHttp';
import type { AppRouter } from '~/server/routers/_app';
import superjson from 'superjson';
import { getUrl } from './shared';
import { getUrl, transformer } from './shared';

export const api = experimental_createTRPCNextAppDirClient<AppRouter>({
config() {
Expand All @@ -19,7 +18,7 @@ export const api = experimental_createTRPCNextAppDirClient<AppRouter>({
enabled: (op) => true,
}),
experimental_nextHttpLink({
transformer: superjson,
transformer,
batch: true,
url: getUrl(),
headers() {
Expand All @@ -37,7 +36,7 @@ export const useAction = experimental_createActionHook<AppRouter>({
links: [
loggerLink(),
experimental_serverActionLink({
transformer: superjson,
transformer,
}),
],
});
53 changes: 53 additions & 0 deletions examples/.experimental/next-app-dir/src/trpc/rq-client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use client';

import type { QueryClient } from '@tanstack/react-query';
import { QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { loggerLink, unstable_httpBatchStreamLink } from '@trpc/client';
import { createTRPCReact } from '@trpc/react-query';
import type { AppRouter } from '~/server/routers/_app';
import { useState } from 'react';
import { createQueryClient, getUrl, transformer } from './shared';

export const trpc = createTRPCReact<AppRouter>();

let clientQueryClientSingleton: QueryClient | undefined = undefined;
const getQueryClient = () => {
if (typeof window === 'undefined') {
// Server: always make a new query client
return createQueryClient();
} else {
// Browser: use singleton pattern to keep the same query client
return (clientQueryClientSingleton ??= createQueryClient());
}
};

export function TRPCReactProvider(props: { children: React.ReactNode }) {
const queryClient = getQueryClient();

const [trpcClient] = useState(() =>
trpc.createClient({
links: [
loggerLink({
enabled: (op) =>
process.env.NODE_ENV === 'development' ||
(op.direction === 'down' && op.result instanceof Error),
}),
unstable_httpBatchStreamLink({
transformer,
url: getUrl(),
headers: { 'x-trpc-source': 'react-query' },
}),
],
}),
);

return (
<trpc.Provider client={trpcClient} queryClient={queryClient}>
<QueryClientProvider client={queryClient}>
{props.children}
<ReactQueryDevtools />
</QueryClientProvider>
</trpc.Provider>
);
}
31 changes: 31 additions & 0 deletions examples/.experimental/next-app-dir/src/trpc/rq-server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'server-only';
import { createHydrationHelpers } from '@trpc/react-query/rsc';
import { auth } from '~/auth';
import type { Context } from '~/server/context';
import { appRouter } from '~/server/routers/_app';
import { createCallerFactory } from '~/server/trpc';
import { headers } from 'next/headers';
import { cache } from 'react';
import { createQueryClient } from './shared';

const createContext = cache(async (): Promise<Context> => {
const _headers = new Headers(headers());
_headers.set('x-trpc-source', 'rsc');

return {
headers: Object.fromEntries(_headers),
session: await auth(),
};
});

/**
* Create a stable getter for the query client that
* will return the same client during the same request.
*/
const getQueryClient = cache(createQueryClient);
const caller = createCallerFactory(appRouter)(createContext);

export const { trpc, HydrateClient } = createHydrationHelpers<typeof appRouter>(
caller,
getQueryClient,
);
5 changes: 2 additions & 3 deletions examples/.experimental/next-app-dir/src/trpc/server-http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { experimental_nextHttpLink } from '@trpc/next/app-dir/links/nextHttp';
import { experimental_createTRPCNextAppDirServer } from '@trpc/next/app-dir/server';
import type { AppRouter } from '~/server/routers/_app';
import { cookies } from 'next/headers';
import superjson from 'superjson';
import { getUrl } from './shared';
import { getUrl, transformer } from './shared';

export const api = experimental_createTRPCNextAppDirServer<AppRouter>({
config() {
Expand All @@ -16,7 +15,7 @@ export const api = experimental_createTRPCNextAppDirServer<AppRouter>({
experimental_nextHttpLink({
batch: true,
url: getUrl(),
transformer: superjson,
transformer,
headers() {
return {
cookie: cookies().toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { experimental_createTRPCNextAppDirServer } from '@trpc/next/app-dir/serv
import { auth } from '~/auth';
import { appRouter } from '~/server/routers/_app';
import { cookies } from 'next/headers';
import superjson from 'superjson';
import { transformer } from './shared';

/**
* This client invokes procedures directly on the server without fetching over HTTP.
Expand All @@ -20,7 +20,7 @@ export const api = experimental_createTRPCNextAppDirServer<typeof appRouter>({
// requests are cached for 5 seconds
revalidate: 5,
router: appRouter,
transformer: superjson,
transformer,
createContext: async () => {
return {
session: await auth(),
Expand Down