Linking &
Navigation.

เจาะลึกระบบการนำทางใน Next.js App Router ตั้งแต่การใช้คอมโพเนนต์ <Link> ไปจนถึงการเขียนโค้ดเปลี่ยนหน้าด้วย useRouter และกลไกเบื้องหลังที่เร่งความเร็วแอปของคุณ

Link

next/link

Declarative

เป็นวิธีหลัก (Primary way) ในการนำทางระหว่างหน้าใน Next.js โดยสืบทอดมาจากแท็ก <a> ของ HTML แต่เพิ่มความสามารถในการทำ Client-side Navigation

  • ดึงข้อมูลหน้าปลายทางล่วงหน้า (Prefetching) อัตโนมัติ
  • สามารถใช้งานได้ทั้งใน Server และ Client Components

useRouter

next/navigation

Programmatic

ใช้เมื่อต้องการสั่งเปลี่ยนหน้าด้วยโค้ด (เช่น หลังจากกดปุ่ม Submit Form หรือเช็คเงื่อนไขเสร็จ)

⚠️ ข้อควรระวัง: ใช้งานได้เฉพาะใน Client Components เท่านั้น (ต้องใส่ "use client")

  • router.push() เพิ่ม History ลงใน Browser
  • router.replace() เปลี่ยนหน้าโดยไม่บันทึก History

Navigation Mechanics

สิ่งที่ทำให้ Next.js แตกต่างจากแอปพลิเคชันแบบดั้งเดิม คือกลไกการนำทางที่ซ่อนอยู่เบื้องหลัง 2 อย่างนี้:

Prefetching (โหลดล่วงหน้า)

เมื่อคอมโพเนนต์ <Link> ปรากฏขึ้นในหน้าจอ (Viewport) ของผู้ใช้ Next.js จะทำการดาวน์โหลด Route ปลายทางนั้นมาเก็บไว้ใน Background ทันที! ทำให้เมื่อผู้ใช้คลิกเปลี่ยนหน้า แอปจะตอบสนองแบบ Instant (ทันทีทันใด)

Tip: หากไม่ต้องการให้โหลดล่วงหน้า สามารถตั้งค่า prefetch={false} ได้

Soft Navigation

เมื่อเกิดการเปลี่ยนหน้า Browser จะ ไม่มีการ Refresh หน้าเว็บใหม่ทั้งหมด (No full page reload) และเฉพาะแค่ส่วนของ Route ที่เปลี่ยนไปเท่านั้นที่จะถูก Render ใหม่ ผลลัพธ์คือ State ของฝั่ง Client (เช่น ค่าที่พิมพ์ใน Input หรือ Sidebar ที่เปิดอยู่) ใน Layout จะถูกเก็บรักษาไว้อย่างสมบูรณ์

Putting it together

ตัวอย่างการใช้งานร่วมกันใน Client Component เมื่อคุณมีทั้งเมนูลิงก์ปกติ และปุ่มที่ต้องการทำงานบางอย่าง (เช่น บันทึกข้อมูล) ก่อนที่จะเปลี่ยนหน้า

"use client";
import Link from 'next/link';
import { useRouter } from 'next/navigation';

export default function NavigationExample() {
  const router = useRouter();

  const handleSubmit = async () => {
    // 1. ทำการบันทึกข้อมูลบางอย่างก่อน
    await saveData();
    // 2. สั่งเปลี่ยนหน้าไปที่ Dashboard
    router.push('/dashboard');
  };

  return (
    <div className="flex gap-4">
      <!-- การใช้งาน Link ทั่วไป -->
      <Link href="/about" className="text-orange-500">
        About Us
      </Link>

      <!-- การใช้งาน useRouter -->
      <button onClick={handleSubmit} className="bg-slate-800 text-white">
        Save & Go
      </button>
    </div>
  );
}