/app/posts/page.tsx
import Link from "next/link";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { Code } from "@/components/code";
import { Row } from "@/components/row";
import { createPost, getPosts } from "@/lib/actions";
export default async function Page() {
const posts = await getPosts();
return (
<Row>
<div className="flex flex-col gap-4">
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/posts/${post.id}`}>{post.title}</Link>
</li>
))}
</ul>
<form action={createPost}>
<Label htmlFor="title">Title</Label>
<Input type="text" name="title" />
<Label htmlFor="content">Content</Label>
<Input type="text" name="content" />
<Button type="submit">Create</Button>
</form>
</div>
<div>
<Code path="/app/posts/page.tsx" />
<Code path="/app/posts/loading.tsx" />
<Code path="/lib/actions.ts" sub={[21, 37]} />
</div>
</Row>
);
}
/app/posts/loading.tsx
import { Skeleton } from "@/components/ui/skeleton";
export default function Loading() {
return <Skeleton className="h-[100px] w-full" />;
}
/lib/actions.ts (lines 22-38)
await delay(1000);
return date;
}
const posts = [
{ id: 1, title: "First Post", content: "This is the first post" },
{ id: 2, title: "Second Post", content: "This is the second post" },
];
export async function createPost(formData: FormData) {
const title = formData.get("title") as string;
const content = formData.get("content") as string;
posts.push({ id: posts.length + 1, title, content });
revalidatePath("/posts");
}