๐ 01 Aug 2025
View on Github โuseEffect()
and async
functions differ and where to use themloading
states for better UX during fetchGET
, POST
, PUT
, DELETE
inside App RouterNextRequest
and NextResponse
for request/response handlingreq.body
and connecting to a mock DBuseEffect()
vs async
FunctionConcept | useEffect() | async Function |
---|---|---|
Purpose | React side-effect (client-side logic) | Run async logic with await |
Usage Context | Inside React components | Anywhere (backend, frontend, utilities) |
Direct Async Use? | โ No โ wrap async inside useEffect | โ Yes, use freely |
Common Use | Fetching, DOM updates | Fetching, DB queries, file I/O |
useEffect(() => {
const fetchData = async () => {
const res = await fetch('/api/data');
const data = await res.json();
setData(data);
};
fetchData();
}, []);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchSomething = async () => {
setLoading(true);
await fetch('/api/data');
setLoading(false);
};
fetchSomething();
}, []);
loading
is toggled to show UI feedback (e.g., spinner/skeleton)export default function handler(req, res) { ... }
export async function GET(req) { ... }
export async function POST(req) { ... }
GET
, POST
, PUT
, DELETE
// app/api/users/route.js
import { NextResponse } from 'next/server';
export async function GET(req) {
return NextResponse.json({ message: 'GET request success' });
}
export async function POST(req) {
const body = await req.json();
return NextResponse.json({ message: 'User created', data: body }, { status: 201 });
}
export async function PUT(req) {
const body = await req.json();
return NextResponse.json({ message: 'User updated', data: body });
}
export async function DELETE(req) {
return NextResponse.json({ message: 'User deleted' }, { status: 204 });
}
NextRequest
& NextResponse
export async function POST(req) {
const body = await req.json();
return NextResponse.json({ message: 'Posted', data: body });
}
import connectDB from '@/lib/db';
import User from '@/models/user';
export async function GET() {
await connectDB();
const users = await User.find();
return NextResponse.json(users);
}
await connectDB()
before running queriesgetServerSideProps()
export async function getServerSideProps(context) {
const res = await fetch('https://api.example.com/posts');
const data = await res.json();
return { props: { posts: data } };
}
export default async function BlogPage() {
const res = await fetch('https://api.example.com/posts', { cache: 'no-store' });
const data = await res.json();
return (
<div>
{data.map((post) => <h2 key={post.id}>{post.title}</h2>)}
</div>
);
}
export const metadata = {
title: "DevFlow โ Ask and Answer Questions",
description: "A developer Q&A platform built with Next.js",
};
export async function generateMetadata({ params }) {
const post = await fetchPostBySlug(params.slug);
return {
title: post.title,
description: post.excerpt,
};
}
<head>
, improves Google rankinggenerateMetadata()
enables dynamic SEO per page (slug-based)Today I finally connected all the pieces of full-stack Next.js โ RESTful API building, request handling, SSR optimization, and SEO best practices. I now fully understand when to use useEffect
vs SSR
, how to manage state during fetch, and how to serve optimized pages for both users and crawlers. This makes my future apps more performant, scalable, and searchable.