Roadmap › Next.js — App Router, Folder Structure, Rendering and Full Stack with SQL Server › Module: Rendering, Data and Caching
Lessons in this course (8)
4. Data fetching, caching and Server Actions
Intermediate★ Must knowLesson 4 of 8
tsx
// Fetch in a Server Component (Next 15+: not cached unless you opt in)
const res = await fetch("https://api.example.com/rates", { next: { revalidate: 300, tags: ["rates"] } });
// Next 16 Cache Components: cache a function's result
async function getCategories() {
"use cache";
return db.query("SELECT Id, Name FROM dbo.Categories");
}Server Actions — functions that run on the server, callable from forms or client code (no API route needed):
tsx
// app/products/new/actions.ts
"use server";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { z } from "zod";
import { createProduct } from "@/lib/products";
const Schema = z.object({ name: z.string().min(2), price: z.coerce.number().positive() });
export async function addProduct(formData: FormData) {
const parsed = Schema.safeParse(Object.fromEntries(formData));
if (!parsed.success) return { error: "Invalid input" };
await createProduct(parsed.data); // auth check here too — actions are public endpoints!
revalidatePath("/products");
redirect("/products");
}
// app/products/new/page.tsx
import { addProduct } from "./actions";
export default function NewProduct() {
return (
<form action={addProduct}>
<input name="name" placeholder="Name" required />
<input name="price" type="number" step="0.01" required />
<button type="submit">Save</button>
</form>
);
}Forms work even before JavaScript loads (progressive enhancement); useActionState and useFormStatus give pending/error states in Client Components.