Full Stack Development
by Tomas Trescak
t.trescak@westernsydney.edu.au
Next.js
/
What's REST API?
- What’s a
REST
API?
- REST Powers everyday apps
- It's everywhere you look
- REST APIs are not just URLs!
REST
/
API Basics
-
Stateless
: No memory between requests
-
Uniform
: Standard HTTP methods
-
Resources
: Everything’s a URL
- Type Unsafe ;(
REST
/
Building APIs in Next.js
import { NextRequest, NextResponse } from "next/server";
interface Post {
id: number;
title: string;
tag: string;
content?: string;
}
let posts: Post[] = [{ id: 1, title: "Learn REST", tag: "coding", content: "Fun!" }];
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const tag = searchParams.get("tag");
const filtered = tag ? posts.filter(p => p.tag === tag) : posts;
return NextResponse.json(filtered);
}
export async function POST(request: NextRequest) {
const newPost: Post = await request.json();
const postWithId = { ...newPost, id: posts.length + 1 };
posts.push(postWithId);
return NextResponse.json({ id: postWithId.id, message: "Post added" }, { status: 201 });
}
/app/api/posts/route.ts
REST
/
Fetching data from APIs
interface Post {
id: number;
title: string;
tag: string;
content?: string;
}
async function fetchPostsByTag(tag: string): Promise<Post[]> {
const response = await fetch(`http://localhost:3000/api/posts?tag=${tag}`);
if (!response.ok) throw new Error("Fetch failed");
const posts: Post[] = await response.json();
return posts;
}
// [{ id: 1, title: "Learn REST", tag: "coding", content: "Fun!" }]
fetchPostsByTag("coding")
.then(posts => console.log(posts))
.catch(err => console.error(err));
REST
/
POSTing data to API
async function createPost(newPost: Omit<Post, "id">): Promise<{
id: number; message: string
}> {
const response = await fetch("http://localhost:3000/api/posts", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(newPost),
});
if (!response.ok) throw new Error("Create failed");
return response.json();
}
const post = { title: "My API Journey", tag: "coding", content: "Wow!" };
createPost(post)
.then(result => console.log(result)) // { id: 2, message: "Post added" }
.catch(err => console.error(err));
Next.js
/
APIs
// Update (PUT)
async function updatePost(id: number, updatedPost: Post):
Promise<{ message: string }> {
const response = await fetch(`http://localhost:3000/api/posts/${id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(updatedPost),
});
if (!response.ok) throw new Error("Update failed");
return response.json();
}
const updated = {
id: 1,
title: "REST Rocks",
tag: "coding",
content: "Updated!"
};
updatePost(1, updated).then(result => console.log(result));
// Patch (PATCH)
async function updatePost(id: number, updatedPost: Partial<Post>):
Promise<{ message: string }> {
const response = await fetch(`http://localhost:3000/api/posts/${id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(updatedPost),
});
if (!response.ok) throw new Error("Update failed");
return response.json();
}
const updated = {
id: 1,
title: "REST Rocks"
};
updatePost(1, updated).then(result => console.log(result));
// Delete (DELETE)
async function deletePost(id: number): Promise<{ message: string }> {
const response = await fetch(`http://localhost:3000/api/posts/${id}`, {
method: "DELETE",
});
if (!response.ok) throw new Error("Delete failed");
return response.json();
}
deletePost(1).then(result => console.log(result));
REST
/
Best Practices
- Clear URLs:
/api/posts
, not
/api/getPosts
- Status Codes:
201
for POST success
- Handle Errors: Check
response.ok
- Pros - Scales
- Cons - Overfetching