๐ 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 Function| Concept | 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 & NextResponseexport 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.