แสดงบทความที่มีป้ายกำกับ client-side แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ client-side แสดงบทความทั้งหมด

วันเสาร์ที่ 1 มีนาคม พ.ศ. 2568

การใช้ SWR ใน Next.js เพื่อดึงข้อมูลแบบ Client-side

ในโลกของการพัฒนาเว็บแอปพลิเคชัน ฝั่ง Frontend ต้องมีวิธีดึงข้อมูลจาก API อย่างมีประสิทธิภาพ ซึ่งใน Next.js มีหลายแนวทางให้เลือกใช้ เช่น getServerSideProps (SSR), getStaticProps (SSG), หรือ Client-side Fetching ซึ่งแต่ละวิธีก็มีข้อดีข้อเสียต่างกันไป

ถ้าพูดถึงการดึงข้อมูลแบบ Client-side แล้ว SWR เป็นตัวเลือกที่หลายคนชอบ เพราะมันช่วยให้การ fetch ข้อมูลลื่นไหล อัปเดตอัตโนมัติ และยังจัดการแคชได้อย่างฉลาด วันนี้เราจะมาทำความรู้จัก SWR และดูวิธีใช้งานใน Next.js กันแบบเข้าใจง่าย ๆ

🔍 SWR คืออะไร?

SWR ย่อมาจาก Stale-While-Revalidate เป็นแนวคิดที่ช่วยให้การดึงข้อมูลเร็วและสดใหม่ตลอดเวลา โดยที่ไม่ต้องให้ผู้ใช้รอนานเกินไป โดยถูกพัฒนาโดยทีมเดียวกับ Next.js (Vercel) ทำให้มันเหมาะกับการใช้ในโปรเจ็กต์ที่พัฒนาโดย Next.js มาก

หลักการของ SWR คือ

  • คืนค่าข้อมูลเก่าจากแคชก่อน เพื่อให้ผู้ใช้เห็นข้อมูลเร็วที่สุด
  • ดึงข้อมูลใหม่จาก API อยู่เบื้องหลัง
  • อัปเดตข้อมูลใหม่ ใน UI อัตโนมัติ

ฟังดูดีใช่ไหม? เพราะมันช่วยให้การโหลดข้อมูลไม่กระตุก และมีประสบการณ์ใช้งานที่ดีขึ้น

🚀 ติดตั้ง SWR

ก่อนอื่น ถ้ายังไม่ได้ติดตั้ง SWR สามารถติดตั้งได้ง่าย ๆ ด้วยคำสั่งนี้

npm install swr
# หรือถ้าใช้ yarn
yarn add swr

เสร็จแล้วก็พร้อมลุย! 🎉

🛠 วิธีใช้ SWR เบื้องต้น

SWR ใช้งานง่ายมาก ๆ เพียงแค่ import และใช้ useSWR ใน React Component

import useSWR from 'swr'

const fetcher = (url) => fetch(url).then(res => res.json())

export default function Profile() {
  const { data, error } = useSWR('/api/user', fetcher)

  if (error) return <div>โหลดข้อมูลไม่สำเร็จ 😢</div>
  if (!data) return <div>กำลังโหลดข้อมูล... ⏳</div>

  return (
    <div>
      <h1>สวัสดี, {data.name}!</h1>
      <p>อีเมล: {data.email}</p>
    </div>
  )
}

อธิบายโค้ด

  • เราใช้ useSWR เพื่อดึงข้อมูลจาก /api/user
  • fetcher คือฟังก์ชันที่ใช้ดึงข้อมูลจาก API
  • ถ้ามี error จะแสดงข้อความผิดพลาด
  • ถ้าข้อมูลยังมาไม่ถึง จะแสดงข้อความ กำลังโหลด...
  • ถ้าทุกอย่างเรียบร้อยแล้ว ก็โชว์ข้อมูลที่ดึงมาได้

ข้อดีของวิธีนี้คือ ไม่ต้องใช้ useEffect หรือจัดการ state เองเลย เพราะ SWR จัดการให้หมด!

⚡️ ทำไม SWR ถึงดีกว่า useEffect + fetch?

บางคนอาจสงสัยว่า "แล้วทำไมไม่ใช้ useEffect กับ fetch ตรง ๆ ล่ะ?" คำตอบคือ SWR ดีกว่าเพราะ

✅ จัดการแคชให้อัตโนมัติ – ไม่ต้องโหลดข้อมูลซ้ำถ้ายังอยู่ในแคช
✅ อัปเดตข้อมูลเมื่อมีการเปลี่ยนแปลง – ไม่ต้อง reload หน้าเอง
✅ รองรับการ Revalidate อัตโนมัติ – ดึงข้อมูลใหม่เมื่อลูกค้ากลับมาที่หน้าเว็บ
✅ รองรับการดึงข้อมูลแบบ on-focus & re-fetch on reconnect – ไม่ต้องกดรีเฟรชเอง

ถ้าใช้ useEffect และ fetch เราต้องเขียนโค้ดจัดการแคชเอง ซึ่งยุ่งยากและซับซ้อนกว่า

🔄 ตัวอย่างการใช้ Mutate และ Revalidate

ถ้าต้องการให้ข้อมูลอัปเดตทันทีโดยไม่ต้องรอ SWR รีเฟรชเอง สามารถใช้ mutate ได้

import useSWR, { mutate } from 'swr'

const fetcher = (url) => fetch(url).then(res => res.json())

export default function Dashboard() {
  const { data } = useSWR('/api/stats', fetcher)

  return (
    <div>
      <h1>ยอดผู้ใช้งาน: {data ? data.users : 'กำลังโหลด...'}</h1>
      <button onClick={() => mutate('/api/stats')}>โหลดข้อมูลใหม่</button>
    </div>
  )
}

เมื่อกดปุ่ม โหลดข้อมูลใหม่ ระบบจะดึงข้อมูลใหม่จาก API ทันที

🔐 ใช้ SWR กับ Authentication

SWR เหมาะกับระบบที่ต้องใช้ Token Authentication เช่น JWT หรือ OAuth เพราะสามารถส่ง Header ไปกับทุก Request ได้ง่าย ๆ

import useSWR from 'swr'

const fetcher = (url) =>
  fetch(url, {
    headers: {
      Authorization: `Bearer ${localStorage.getItem('token')}`,
    },
  }).then((res) => res.json())

export default function UserProfile() {
  const { data, error } = useSWR('/api/profile', fetcher)

  if (error) return <div>โหลดข้อมูลไม่สำเร็จ</div>
  if (!data) return <div>กำลังโหลด...</div>

  return <h1>ชื่อผู้ใช้: {data.username}</h1>
}


🔥 การใช้งาน SWR กับ GraphQL

ถ้าใช้ GraphQL เราก็สามารถใช้ SWR ได้ โดยเปลี่ยนจาก fetch เป็นการส่ง Query ไปยัง API

const fetcher = (query) =>
  fetch('/graphql', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ query }),
  }).then((res) => res.json())

const GET_USER = `
  {
    user {
      name
      email
    }
  }
`

export default function UserProfile() {
  const { data, error } = useSWR(GET_USER, fetcher)

  if (error) return <div>โหลดข้อมูลไม่สำเร็จ</div>
  if (!data) return <div>กำลังโหลด...</div>

  return <h1>ชื่อ: {data.user.name}</h1>
}

📌 สรุป

SWR เป็นเครื่องมือที่ช่วยให้การดึงข้อมูลแบบ Client-side ง่ายขึ้น โดยที่ไม่ต้องจัดการแคชเอง รองรับการอัปเดตข้อมูลอัตโนมัติ และมีประสิทธิภาพสูงกว่าการใช้ useEffect + fetch แบบเดิม ๆ
✅ เหมาะกับ

  • ดึงข้อมูลที่เปลี่ยนแปลงบ่อย เช่น ยอดไลก์, คอมเมนต์, จำนวนผู้ใช้
  • แสดงข้อมูลให้ผู้ใช้เร็วที่สุด โดยใช้แคช
  • อัปเดตข้อมูลอัตโนมัติ โดยไม่ต้องรีเฟรชหน้า

ถ้าคุณใช้ Next.js อยู่แล้ว ลองเอา SWR ไปใช้ดู รับรองว่าชีวิตง่ายขึ้นแน่นอน! 🚀

วันพุธที่ 19 กุมภาพันธ์ พ.ศ. 2568

การใช้ Link และ useRouter เพื่อการนำทางใน Next.js

การนำทาง (Navigation) เป็นหนึ่งในองค์ประกอบสำคัญของเว็บแอปพลิเคชัน เพราะมันทำให้ผู้ใช้สามารถเคลื่อนที่ไปมาระหว่างหน้าได้อย่างราบรื่น ใน Next.js ซึ่งเป็น React Framework ที่ได้รับความนิยมสูง เรามีเครื่องมือสองตัวที่ใช้ในการนำทางหลัก ๆ ได้แก่ Link และ useRouter

ในบทความนี้ เราจะมาทำความเข้าใจว่า Link และ useRouter คืออะไร ใช้งานยังไง และมีกรณีไหนบ้างที่ควรใช้ตัวไหน พร้อมตัวอย่างโค้ดที่เข้าใจง่าย


ทำไมต้องใช้ Link และ useRouter?

ใน Next.js เราสามารถใช้ <a href="..."> แบบปกติได้ แต่ปัญหาคือมันจะโหลดหน้าใหม่ทุกครั้งที่คลิกลิงก์ ซึ่งไม่ใช่สิ่งที่เราต้องการสำหรับเว็บแอปที่ต้องการความเร็วและประสิทธิภาพสูง

Link และ useRouter แก้ปัญหานี้ได้อย่างไร?

  • Link ช่วยให้เราสามารถทำ client-side navigation ได้โดยที่ไม่ต้องโหลดหน้าใหม่
  • useRouter ให้เราควบคุมการนำทางด้วยโค้ด เช่น การเปลี่ยนเส้นทาง (redirect) หรือดึงค่าพารามิเตอร์จาก URL


1. Link – วิธีสร้างลิงก์นำทางแบบง่าย ๆ

ถ้าเราต้องการสร้างลิงก์ระหว่างหน้าต่าง ๆ ใน Next.js วิธีที่ถูกต้องคือใช้ <Link> จาก next/link

ตัวอย่างการใช้งานพื้นฐาน

import Link from 'next/link';

export default function Home() {
  return (
    <div>
      <h1>หน้าแรก</h1>
      <Link href="/about">ไปที่หน้า About</Link>
    </div>
  );
}


✅ ทำไมต้องใช้ Link แทน <a>?

  • เมื่อใช้ Link Next.js จะ โหลดหน้าใหม่ให้เร็วขึ้น เพราะมันใช้เทคนิคการ prefetch (โหลดล่วงหน้า)
  • ไม่ต้องโหลด HTML ใหม่ทั้งหน้า เหมือนกับ Single Page Application (SPA)
  • การใช้งานง่าย ไม่ต้องเขียนโค้ด JavaScript เพิ่ม


2. useRouter – การควบคุมเส้นทางด้วย JavaScript

ในบางกรณี เราอาจต้องนำทางโดยไม่ใช้ <Link> เช่น การเปลี่ยนหน้าเมื่อผู้ใช้กดปุ่ม หรือเปลี่ยนเส้นทางหลังจากทำบางอย่างเสร็จ (redirect)

Next.js มี useRouter จาก next/router ที่ช่วยให้เราควบคุมเส้นทางได้ผ่านโค้ด JavaScript

ตัวอย่างการใช้งาน useRouter เพื่อเปลี่ยนหน้า

import { useRouter } from 'next/router';

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

  const goToAbout = () => {
    router.push('/about');
  };

  return (
    <div>
      <h1>หน้าแรก</h1>
      <button onClick={goToAbout}>ไปที่หน้า About</button>
    </div>
  );
}


✅ router.push(url) ทำอะไรได้บ้าง?

  • เปลี่ยนเส้นทางโดยไม่ต้องใช้ <Link>
  • ทำให้การเปลี่ยนหน้าเกิดขึ้นจากอีเวนต์ เช่น คลิกปุ่ม หรือส่งฟอร์ม
  • รองรับการใช้พารามิเตอร์ใน URL



3. ส่งค่าผ่าน URL ด้วย Query Parameters

ในบางกรณี เราอาจต้องส่งข้อมูลไปพร้อมกับ URL เช่น /profile?user=JohnDoe

วิธีส่งค่าไปยังหน้าอื่น

import { useRouter } from 'next/router';

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

  const goToProfile = () => {
    router.push({
      pathname: '/profile',
      query: { user: 'JohnDoe' },
    });
  };

  return (
    <div>
      <h1>หน้าแรก</h1>
      <button onClick={goToProfile}>ไปที่โปรไฟล์ของ John Doe</button>
    </div>
  );
}


4. ดึงค่าพารามิเตอร์จาก URL

เมื่อเราส่งค่าไปกับ URL แล้ว เราก็ต้องดึงค่ามาใช้ที่หน้าปลายทาง

วิธีดึงค่าจาก query parameters

import { useRouter } from 'next/router';

export default function Profile() {
  const router = useRouter();
  const { user } = router.query; // ดึงค่าพารามิเตอร์จาก URL

  return (
    <div>
      <h1>โปรไฟล์ของ {user || 'ไม่ทราบชื่อ'}</h1>
    </div>
  );
}

✅ จุดที่ต้องระวัง

  • ค่า router.query อาจเป็น undefined ถ้าหน้าโหลดครั้งแรก ต้องเช็กก่อนใช้


5. นำทางแบบ Dynamic Routing

ถ้าเรามีเส้นทางแบบไดนามิก เช่น /blog/[id] และอยากเปลี่ยนหน้าไปที่ /blog/123 เราสามารถใช้ router.push() ได้แบบนี้

ตัวอย่าง Dynamic Routing

import { useRouter } from 'next/router';

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

  const goToBlog = (id) => {
    router.push(`/blog/${id}`);
  };

  return (
    <div>
      <h1>รายการบทความ</h1>
      <button onClick={() => goToBlog(123)}>อ่านบทความ 123</button>
    </div>
  );
}

ที่หน้า /blog/[id].js เราสามารถดึงค่า id จาก URL ได้แบบนี้

import { useRouter } from 'next/router';

export default function BlogPost() {
  const router = useRouter();
  const { id } = router.query;

  return <h1>บทความที่ {id}</h1>;
}


Link กับ useRouter ควรใช้เมื่อไหร่?

กรณี                                                ใช้ Link    ใช้ useRouter
ลิงก์ระหว่างหน้า                                    ✅              ❌
นำทางจากปุ่มหรืออีเวนต์                      ❌              ✅
ส่งค่าไปกับ URL                                   ❌              ✅
Redirect หลังทำบางอย่างเสร็จ             ❌              ✅
ต้องการโหลดล่วงหน้า (prefetch)          ✅             ❌


สรุป

  • Link ใช้สำหรับการนำทางแบบปกติที่ต้องการให้ Next.js จัดการ prefetch ให้
  • useRouter ใช้เมื่อต้องการนำทางด้วยโค้ด JavaScript เช่น การ redirect หรือดึงค่าจาก URL
  • Next.js ช่วยให้การนำทางรวดเร็วและมีประสิทธิภาพกว่าการใช้ <a> แบบดั้งเดิม

หวังว่าบทความนี้จะช่วยให้คุณเข้าใจการนำทางใน Next.js มากขึ้น!

การใช้ Image Optimization ใน Next.js: โหลดไว SEO ดี ประหยัดแบนด์วิธ!

เคยเจอปัญหาเว็บโหลดช้าเพราะรูปภาพขนาดใหญ่หรือเปล่า? 📷 ถ้าใช่ Next.js มีฟีเจอร์ Image Optimization ที่ช่วยให้รูปภาพโหลดเร็วขึ้น อัตโนมัติ ไม...