React 19 cùng với Next.js App Router đã đánh dấu bước chuyển mình lớn nhất của hệ sinh thái React kể từ thời điểm React Hooks ra đời (2018). Chúng ta không còn xây dựng các ứng dụng Single Page Application (SPA) hoàn toàn chạy ở trình duyệt nữa, mà chuyển sang mô hình lai (Hybrid Architecture) kết hợp sức mạnh tính toán của Server và độ mượt mà tương tác của Client.
Nếu bạn vẫn đang dùng `useEffect` để fetch dữ liệu khi component mount, bài viết này sẽ giúp bạn nâng cấp tư duy lập trình lên tiêu chuẩn hiện đại nhất.
1. Server Components vs Client Components: Đừng hiểu lầm
Trong Next.js App Router, mọi component mặc định đều là Server Component trừ khi bạn thêm chỉ thị 'use client' ở đầu file.
- Server Components (Mặc định):
- Chỉ chạy trên máy chủ (Node.js/Edge Runtime).
- Không gửi JavaScript của component xuống trình duyệt -> Bundle size = 0 KB.
- Có thể trực tiếp truy vấn cơ sở dữ liệu (Prisma, Drizzle, Supabase) hoặc đọc file từ hệ điều hành.
- Không thể dùng React Hooks (
useState,useEffect) hay lắng nghe event DOM (onClick). - Client Components (
'use client'): - Render trước một phần HTML trên server và sau đó hydrate (gắn logic) trên trình duyệt.
- Dùng cho các tương tác người dùng: form inputs, modals, animations, event listeners.
2. Server Actions: Đột phá trong xử lý Mutations
Trước đây, để submit một form, bạn cần tạo file API Route (/api/feedback), viết hàm fetch('/api/feedback', { method: 'POST' }), xử lý loading state bằng useState và validate ở 2 đầu.
Với Server Actions, bạn có thể viết một hàm chạy trực tiếp trên máy chủ và truyền thẳng vào thuộc tính action của thẻ :
"use server";
import { z } from "zod";
import { db } from "@/lib/db";
import { revalidatePath } from "next/cache";
const feedbackSchema = z.object({
name: z.string().min(2, "Tên quá ngắn"),
email: z.string().email("Email không hợp lệ"),
message: z.string().min(10, "Nội dung phản hồi tối thiểu 10 ký tự"),
});
export async function submitFeedbackAction(prevState: any, formData: FormData) {
const rawData = {
name: formData.get("name"),
email: formData.get("email"),
message: formData.get("message"),
};
const parsed = feedbackSchema.safeParse(rawData);
if (!parsed.success) {
return { success: false, errors: parsed.error.flatten().fieldErrors };
}
try {
await db.feedbacks.create({ data: parsed.data });
// Làm mới cache trang feedbacks ngay lập tức
revalidatePath("/admin/feedbacks");
return { success: true, message: "Cảm ơn bạn đã gửi phản hồi!" };
} catch (error) {
return { success: false, message: "Đã có lỗi xảy ra từ máy chủ." };
}
}3. Bộ đôi Hook mới: useActionState & useOptimistic
React 19 giới thiệu các Hook mạnh mẽ giúp kết nối giao diện phía client với Server Actions mượt mà:
useActionState: Tự động quản lý kết quả trả về (state), trạng thái đang gửi (isPending) và hàm action trigger.useOptimistic: Cập nhật UI ngay lập tức trước khi server kịp phản hồi, mang lại trải nghiệm tương tác không có độ trễ.
"use client";
import { useActionState } from "react";
import { submitFeedbackAction } from "@/actions/feedback";
export function FeedbackForm() {
const [state, formAction, isPending] = useActionState(submitFeedbackAction, null);
return (
<form action={formAction} className="space-y-4 max-w-md">
{state?.success && (
<p className="p-3 rounded bg-emerald-500/10 text-emerald-400 text-sm">
{state.message}
</p>
)}
<div>
<input name="name" placeholder="Họ và tên" className="w-full p-2 bg-zinc-900 border rounded" />
{state?.errors?.name && <span className="text-xs text-red-400">{state.errors.name[0]}</span>}
</div>
<div>
<textarea name="message" placeholder="Nội dung" className="w-full p-2 bg-zinc-900 border rounded" />
{state?.errors?.message && <span className="text-xs text-red-400">{state.errors.message[0]}</span>}
</div>
<button
disabled={isPending}
type="submit"
className="px-4 py-2 bg-emerald-500 text-black font-semibold rounded disabled:opacity-50"
>
{isPending ? "Đang gửi phản hồi..." : "Gửi ngay"}
</button>
</form>
);
}Bạn đang gặp vấn đề tương tự?
Tôi có thể giúp bạn tối ưu website — liên hệ để trao đổi miễn phí.
Kết luận
React Server Components và Server Actions không phải là sự thay thế cho React truyền thống, mà là sự hoàn thiện về mặt kiến trúc. Nắm vững mô hình này giúp bạn tiết kiệm đáng kể thời gian viết boilerplate code, đồng thời mang lại trải nghiệm tải trang nhanh và an toàn hơn cho người dùng.
Muốn thảo luận thêm?
Nếu bạn có câu hỏi cụ thể về web performance, React, hoặc muốn hợp tác dự án — liên hệ trực tiếp với tôi.