Data fetching & action typing
Fetch data on the server with typed JSON, control caching/revalidation, and create typed Server Actions for forms and mutations.
Intro
Goal: Fetch data in server components with typed JSON, configure cache/revalidate, and build typed Server Actions for mutations.
- Typed fetch helpers
- Cache: revalidate vs no-store
- Server Actions with forms
Typed fetch helper
Create a small json<T> helper to decode responses and throw on non-200. Use revalidate for ISR-like caching.
// app/lib/http.ts
export async function json<T>(res: Response): Promise<T> {
if (!res.ok) throw new Error(`HTTP ${res.status}`)
return (await res.json()) as T
}
// app/page.tsx (server)
export type Post = { id: number; title: string }
export default async function Page() {
const res = await fetch("https://example.com/api/posts", { next: { revalidate: 60 } })
const posts = await json<Post[]>(res)
return (
<main style={{ display: "grid", gap: 8 }}>
<h1>Posts</h1>
<ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>
</main>
)
}All lessons in this course
- App Router types; server vs client components
- Data fetching & action typing
- Env typing and config