Skip to content

Commit

Permalink
feat: trpc prefetching (#1932)
Browse files Browse the repository at this point in the history
  • Loading branch information
juliusmarminge authored Jul 5, 2024
1 parent a1a4b87 commit 42a485a
Show file tree
Hide file tree
Showing 15 changed files with 487 additions and 425 deletions.
5 changes: 5 additions & 0 deletions .changeset/spotty-donkeys-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-t3-app": minor
---

feat: add trpc rsc prefetching
10 changes: 5 additions & 5 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@
"@prisma/adapter-planetscale": "^5.14.0",
"@prisma/client": "^5.14.0",
"@t3-oss/env-nextjs": "^0.10.1",
"@tanstack/react-query": "^5.39.0",
"@trpc/client": "11.0.0-rc.377",
"@trpc/next": "11.0.0-rc.377",
"@trpc/react-query": "11.0.0-rc.377",
"@trpc/server": "11.0.0-rc.377",
"@tanstack/react-query": "^5.49.2",
"@trpc/client": "11.0.0-rc.441",
"@trpc/next": "11.0.0-rc.441",
"@trpc/react-query": "11.0.0-rc.441",
"@trpc/server": "11.0.0-rc.441",
"@types/fs-extra": "^11.0.4",
"@types/gradient-string": "^1.1.6",
"@types/node": "^20.12.12",
Expand Down
8 changes: 6 additions & 2 deletions cli/src/installers/trpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,13 @@ export const trpcInstaller: Installer = ({
path.join(
extrasDir,
"src/app/_components",
packages?.tailwind.inUse ? "create-post-tw.tsx" : "create-post.tsx"
packages?.tailwind.inUse ? "post-tw.tsx" : "post.tsx"
),
path.join(projectDir, "src/app/_components/create-post.tsx"),
path.join(projectDir, "src/app/_components/post.tsx"),
],
[
path.join(extrasDir, "src/trpc/query-client.ts"),
path.join(projectDir, "src/trpc/query-client.ts"),
]
);
} else {
Expand Down
43 changes: 0 additions & 43 deletions cli/template/extras/src/app/_components/create-post-tw.tsx

This file was deleted.

44 changes: 0 additions & 44 deletions cli/template/extras/src/app/_components/create-post.tsx

This file was deleted.

50 changes: 50 additions & 0 deletions cli/template/extras/src/app/_components/post-tw.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"use client";

import { useState } from "react";

import { api } from "~/trpc/react";

export function LatestPost() {
const [latestPost] = api.post.getLatest.useSuspenseQuery();

const utils = api.useUtils();
const [name, setName] = useState("");
const createPost = api.post.create.useMutation({
onSuccess: async () => {
await utils.post.invalidate();
setName("");
},
});

return (
<div className="w-full max-w-xs">
{latestPost ? (
<p className="truncate">Your most recent post: {latestPost.name}</p>
) : (
<p>You have no posts yet.</p>
)}
<form
onSubmit={(e) => {
e.preventDefault();
createPost.mutate({ name });
}}
className="flex flex-col gap-2"
>
<input
type="text"
placeholder="Title"
value={name}
onChange={(e) => setName(e.target.value)}
className="w-full rounded-full px-4 py-2 text-black"
/>
<button
type="submit"
className="rounded-full bg-white/10 px-10 py-3 font-semibold transition hover:bg-white/20"
disabled={createPost.isPending}
>
{createPost.isPending ? "Submitting..." : "Submit"}
</button>
</form>
</div>
);
}
54 changes: 54 additions & 0 deletions cli/template/extras/src/app/_components/post.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"use client";

import { useState } from "react";

import { api } from "~/trpc/react";
import styles from "../index.module.css";

export function LatestPost() {
const [latestPost] = api.post.getLatest.useSuspenseQuery();

const utils = api.useUtils();
const [name, setName] = useState("");
const createPost = api.post.create.useMutation({
onSuccess: async () => {
await utils.post.invalidate();
setName("");
},
});

return (
<div className={styles.showcaseContainer}>
{latestPost ? (
<p className={styles.showcaseText}>
Your most recent post: {latestPost.name}
</p>
) : (
<p className={styles.showcaseText}>You have no posts yet.</p>
)}

<form
onSubmit={(e) => {
e.preventDefault();
createPost.mutate({ name });
}}
className={styles.form}
>
<input
type="text"
placeholder="Title"
value={name}
onChange={(e) => setName(e.target.value)}
className={styles.input}
/>
<button
type="submit"
className={styles.submitButton}
disabled={createPost.isPending}
>
{createPost.isPending ? "Submitting..." : "Submit"}
</button>
</form>
</div>
);
}
115 changes: 50 additions & 65 deletions cli/template/extras/src/app/page/with-auth-trpc-tw.tsx
Original file line number Diff line number Diff line change
@@ -1,82 +1,67 @@
import Link from "next/link";

import { CreatePost } from "~/app/_components/create-post";
import { LatestPost } from "~/app/_components/post";
import { getServerAuthSession } from "~/server/auth";
import { api } from "~/trpc/server";
import { api, HydrateClient } from "~/trpc/server";

export default async function Home() {
const hello = await api.post.hello({ text: "from tRPC" });
const session = await getServerAuthSession();

return (
<main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white">
<div className="container flex flex-col items-center justify-center gap-12 px-4 py-16 ">
<h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]">
Create <span className="text-[hsl(280,100%,70%)]">T3</span> App
</h1>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:gap-8">
<Link
className="flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 hover:bg-white/20"
href="https://create.t3.gg/en/usage/first-steps"
target="_blank"
>
<h3 className="text-2xl font-bold">First Steps →</h3>
<div className="text-lg">
Just the basics - Everything you need to know to set up your
database and authentication.
</div>
</Link>
<Link
className="flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 hover:bg-white/20"
href="https://create.t3.gg/en/introduction"
target="_blank"
>
<h3 className="text-2xl font-bold">Documentation →</h3>
<div className="text-lg">
Learn more about Create T3 App, the libraries it uses, and how to
deploy it.
</div>
</Link>
</div>
<div className="flex flex-col items-center gap-2">
<p className="text-2xl text-white">
{hello ? hello.greeting : "Loading tRPC query..."}
</p>
void api.post.getLatest.prefetch();

<div className="flex flex-col items-center justify-center gap-4">
<p className="text-center text-2xl text-white">
{session && <span>Logged in as {session.user?.name}</span>}
</p>
return (
<HydrateClient>
<main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white">
<div className="container flex flex-col items-center justify-center gap-12 px-4 py-16 ">
<h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]">
Create <span className="text-[hsl(280,100%,70%)]">T3</span> App
</h1>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:gap-8">
<Link
href={session ? "/api/auth/signout" : "/api/auth/signin"}
className="rounded-full bg-white/10 px-10 py-3 font-semibold no-underline transition hover:bg-white/20"
className="flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 hover:bg-white/20"
href="https://create.t3.gg/en/usage/first-steps"
target="_blank"
>
{session ? "Sign out" : "Sign in"}
<h3 className="text-2xl font-bold">First Steps →</h3>
<div className="text-lg">
Just the basics - Everything you need to know to set up your
database and authentication.
</div>
</Link>
<Link
className="flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 hover:bg-white/20"
href="https://create.t3.gg/en/introduction"
target="_blank"
>
<h3 className="text-2xl font-bold">Documentation →</h3>
<div className="text-lg">
Learn more about Create T3 App, the libraries it uses, and how
to deploy it.
</div>
</Link>
</div>
</div>

<CrudShowcase />
</div>
</main>
);
}

async function CrudShowcase() {
const session = await getServerAuthSession();
if (!session?.user) return null;

const latestPost = await api.post.getLatest();
<div className="flex flex-col items-center gap-2">
<p className="text-2xl text-white">
{hello ? hello.greeting : "Loading tRPC query..."}
</p>

return (
<div className="w-full max-w-xs">
{latestPost ? (
<p className="truncate">Your most recent post: {latestPost.name}</p>
) : (
<p>You have no posts yet.</p>
)}
<div className="flex flex-col items-center justify-center gap-4">
<p className="text-center text-2xl text-white">
{session && <span>Logged in as {session.user?.name}</span>}
</p>
<Link
href={session ? "/api/auth/signout" : "/api/auth/signin"}
className="rounded-full bg-white/10 px-10 py-3 font-semibold no-underline transition hover:bg-white/20"
>
{session ? "Sign out" : "Sign in"}
</Link>
</div>
</div>

<CreatePost />
</div>
{session?.user && <LatestPost />}
</div>
</main>
</HydrateClient>
);
}
Loading

0 comments on commit 42a485a

Please sign in to comment.