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: trpc prefetching #1932

Merged
merged 6 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading