วันเสาร์ที่ 5 เมษายน พ.ศ. 2568

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

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

🌟 ทำไมต้องใช้ Image Optimization ใน Next.js?

✅ ลดขนาดไฟล์รูปภาพ โดยอัตโนมัติ 📉
✅ รองรับการแปลงเป็น WebP ที่โหลดเร็วกว่า JPEG/PNG ⚡
✅ รองรับ Lazy Loading โหลดเฉพาะตอนที่รูปจะถูกแสดง 💤
✅ รองรับการปรับขนาดรูปแบบอัตโนมัติ ตามหน้าจอผู้ใช้ 📱
✅ ทำให้ SEO ดีขึ้น เพราะเว็บโหลดเร็ว 🚀

วันนี้เราจะมาเรียนรู้วิธีใช้ Next.js Image Optimization อย่างมือโปร 💪

📌 เริ่มต้นใช้งาน Image Optimization ใน Next.js

Next.js มีคอมโพเนนต์ <Image> ที่ช่วยจัดการรูปภาพอัตโนมัติ ให้ใช้แทน <img> ปกติ

📂 สร้างไฟล์ pages/index.js แล้วใส่โค้ดนี้

import Image from 'next/image';

export default function Home() {
  return (
    <div>
      <h1>🚀 ใช้ Next.js Image Optimization</h1>
      <Image
        src="/images/sample.jpg"
        alt="รูปตัวอย่าง"
        width={500}
        height={300}
      />
    </div>
  );
}

🔹 อธิบายโค้ด

  • <Image> – ใช้แทน <img>
  • src – พาธของรูปภาพ (ใช้ /public/images/sample.jpg)
  • alt – คำอธิบายรูป (สำคัญต่อ SEO)
  • width & height – กำหนดขนาดรูป (Next.js ปรับขนาดให้เหมาะสม)


🎯 เปรียบเทียบ <Image> กับ <img>

คุณสมบัติ <Image> (Next.js) <img> (HTML)
Lazy Loading ✅ อัตโนมัติ ❌ ต้องเพิ่ม loading="lazy" เอง
ปรับขนาดรูปอัตโนมัติ ✅ ❌
รองรับ WebP ✅ ❌
SEO Friendly ✅ ❌

💡 สรุป: ใช้ <Image> จะช่วยให้รูปภาพโหลดเร็วขึ้น โดยที่เราไม่ต้องทำอะไรเพิ่มเลย!


🖼 ใช้ Image Optimization กับรูปภาพจากภายนอก

ถ้ารูปภาพของคุณ อยู่ใน CDN หรือโดเมนอื่น ต้องเพิ่มโดเมนนั้นใน next.config.js

📂 แก้ไขไฟล์ next.config.js

module.exports = {
  images: {
    domains: ['example.com', 'cdn.example.com'],
  },
};

🔹 ตัวอย่างการใช้รูปจาก CDN

<Image
  src="https://example.com/image.jpg"
  width={500}
  height={300}
  alt="รูปจาก CDN"
/>

💡 ทำไมต้องเพิ่มโดเมนใน next.config.js?

Next.js ต้องการควบคุมความปลอดภัยและประสิทธิภาพ จึงไม่ให้โหลดรูปจากภายนอกโดยตรง ถ้าไม่ระบุไว้

📏 ปรับขนาดรูปภาพอัตโนมัติ

สามารถใช้ layout เพื่อให้รูปภาพปรับขนาดตามคอนเทนต์ได้

🔹 layout="responsive" (ขนาดเปลี่ยนตามหน้าจอ)

<Image
  src="/images/sample.jpg"
  alt="รูปตัวอย่าง"
  layout="responsive"
  width={16}
  height={9}
/>

📌 ภาพจะปรับขนาดตามสัดส่วน 16:9 โดยอัตโนมัติ

🔹 layout="intrinsic" (ขนาดเท่าต้นฉบับ)

<Image
  src="/images/sample.jpg"
  alt="รูปตัวอย่าง"
  layout="intrinsic"
  width={500}
  height={300}
/>

📌 ภาพจะใช้ขนาดจริงของไฟล์ และขยายตามหน้าจอ

🔹 layout="fill" (ให้รูปเต็มพื้นที่ของ container)

<div style={{ position: 'relative', width: '100%', height: '400px' }}>
  <Image
    src="/images/sample.jpg"
    alt="รูปตัวอย่าง"
    layout="fill"
    objectFit="cover"
  />
</div>

📌 รูปจะถูกยืดให้เต็ม container และ objectFit="cover" ป้องกันการเสียสัดส่วน

⚡ เปลี่ยนฟอร์แมตรูปเป็น WebP อัตโนมัติ

Next.js รองรับ WebP โดยไม่ต้องแปลงเอง!

<Image
  src="/images/sample.jpg"
  alt="รูปตัวอย่าง"
  width={500}
  height={300}
  quality={80}
/>

📌 Next.js จะสร้างรูปแบบ WebP อัตโนมัติถ้าผู้ใช้รองรับ


🔄 ใช้ Blur Effect สำหรับรูปโหลดช้า

Next.js มี blur effect ช่วยให้รูปที่โหลดช้า ไม่ทำให้หน้าเว็บดูแย่

<Image
  src="/images/sample.jpg"
  alt="รูปตัวอย่าง"
  width={500}
  height={300}
  placeholder="blur"
  blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
/>

📌 ภาพจะมีเอฟเฟกต์เบลอจนกว่าจะโหลดเสร็จ

🔥 ใช้ Next.js Image API


Next.js มี API สำหรับ Resize และ Optimize รูป อัตโนมัติ

📌 ตัวอย่างการใช้ API

https://yourdomain.com/_next/image?url=/images/sample.jpg&w=500&q=75

🔹 w=500 → ปรับขนาดรูปเป็น 500px
🔹 q=75 → ลดคุณภาพให้เหลือ 75%

📌 สรุป

✅ ใช้ <Image> แทน <img> เพื่อให้เว็บโหลดเร็ว
✅ รองรับ Lazy Loading และ WebP อัตโนมัติ
✅ ปรับขนาดรูป ให้เหมาะสมกับทุกอุปกรณ์
✅ ใช้ layout ต่างๆ เพื่อให้รูปแสดงผลตามต้องการ
✅ ใช้ API ของ Next.js ช่วย Optimize รูปให้เบาและเร็ว

อยากให้เว็บโหลดเร็ว + SEO ดีขึ้น? ใช้ Next.js Image Optimization เลย! 🚀

วันศุกร์ที่ 4 เมษายน พ.ศ. 2568

วิธีเพิ่ม Meta Tags และทำ SEO ใน Next.js ให้เว็บติดอันดับ Google

ถ้าคุณทำเว็บด้วย Next.js แล้วอยากให้เว็บของคุณ ติดอันดับ Google หรือมี SEO (Search Engine Optimization) ที่ดีขึ้น Meta Tags เป็นสิ่งที่ต้องรู้!

Meta Tags คืออะไร? 🤔

Meta Tags คือ โค้ดที่ซ่อนอยู่ใน <head> ของเว็บเพจ ซึ่งช่วยให้ Google, Facebook, Twitter และแพลตฟอร์มอื่นๆ เข้าใจว่าเว็บของเราคืออะไร

ทำไม Meta Tags สำคัญ?

✅ ช่วยให้ Google จัดอันดับเว็บของคุณดีขึ้น (SEO)
✅ ช่วยให้ Social Media แสดงพรีวิวสวยๆ เวลาแชร์ลิงก์
✅ ช่วยให้เว็บโหลดเร็วขึ้น (Performance Boost)

วันนี้เราจะมาเรียนรู้ว่า Next.js ช่วยให้การเพิ่ม Meta Tags และการทำ SEO ง่ายขึ้นได้ยังไง 💡


🚀 เริ่มต้น: ใช้ <Head> ใน Next.js

ใน Next.js เราใช้คอมโพเนนต์ <Head> จาก next/head เพื่อใส่ Meta Tags ได้ง่ายๆ

🔹 ตัวอย่างใน pages/index.js

import Head from 'next/head';

export default function Home() {
  return (
    <>
      <Head>
        <title>สุดยอดเว็บ Next.js | ติดอันดับ Google ง่ายๆ 🚀</title>
        <meta name="description" content="เว็บ Next.js ที่สุดยอดสำหรับการทำ SEO และ Meta Tags" />
        <meta name="keywords" content="Next.js, SEO, Meta Tags, Google Ranking" />
        <meta name="author" content="Your Name" />
      </Head>
      <main>
        <h1>🔥 ยินดีต้อนรับสู่สุดยอดเว็บ Next.js!</h1>
      </main>
    </>
  );
}

🔹 อธิบายโค้ด

✅ <title> – เป็นชื่อของหน้าเว็บที่จะแสดงบนแท็บเบราว์เซอร์
✅ <meta name="description"> – บอก Google ว่าเว็บนี้เกี่ยวกับอะไร
✅ <meta name="keywords"> – เพิ่มคีย์เวิร์ดที่ช่วยให้ Google เข้าใจเว็บเรา (แต่ Google ให้ความสำคัญกับ description มากกว่า)
✅ <meta name="author"> – บอกว่าใครเป็นเจ้าของเว็บ


🎯 ปรับแต่ง Meta Tags ให้ Social Media

ถ้าเราแชร์ลิงก์บน Facebook, Twitter หรือ LINE แล้วอยากให้มี รูปภาพ, ชื่อเว็บ และคำอธิบายสวยๆ เราต้องเพิ่ม Open Graph (OG) Tags

🔹 ตัวอย่าง Open Graph Tags

<Head>
  <meta property="og:title" content="สุดยอดเว็บ Next.js | ติดอันดับ Google ง่ายๆ 🚀" />
  <meta property="og:description" content="เว็บ Next.js ที่สุดยอดสำหรับการทำ SEO และ Meta Tags" />
  <meta property="og:image" content="https://yourwebsite.com/og-image.jpg" />
  <meta property="og:url" content="https://yourwebsite.com/" />
  <meta property="og:type" content="website" />
</Head>

🔹 อธิบายโค้ด

✅ og:title – ชื่อของเว็บเมื่อแชร์บน Facebook
✅ og:description – คำอธิบายเว็บ
✅ og:image – รูปภาพพรีวิว (แนะนำขนาด 1200x630px)
✅ og:url – URL ของเว็บ
✅ og:type – ประเภทของเนื้อหา เช่น website, article


🐦 เพิ่ม Twitter Meta Tags

ถ้าอยากให้เว็บดูดีตอนแชร์บน Twitter ให้ใช้ Twitter Card Tags

<Head>
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:title" content="สุดยอดเว็บ Next.js | ติดอันดับ Google ง่ายๆ 🚀" />
  <meta name="twitter:description" content="เว็บ Next.js ที่สุดยอดสำหรับการทำ SEO และ Meta Tags" />
  <meta name="twitter:image" content="https://yourwebsite.com/twitter-image.jpg" />
</Head>

🔹 อธิบายโค้ด

✅ twitter:card – summary_large_image ทำให้แสดงภาพใหญ่
✅ twitter:title – ชื่อของเว็บ
✅ twitter:description – คำอธิบาย
✅ twitter:image – รูปภาพที่ใช้แสดงบน Twitter


🏆 การทำ SEO ให้ Next.js ติดอันดับ Google

นอกจาก Meta Tags แล้ว Next.js ยังช่วยเรื่อง SEO ได้อีกหลายอย่าง เช่น SSR, SSG และ Dynamic Meta Tags

1️⃣ ใช้ Server-side Rendering (SSR) เพื่อโหลด Meta Tags แบบไดนามิก

บางหน้าเว็บ (เช่น บทความ หรือหน้าสินค้า) อาจต้องใช้ Meta Tags ที่เปลี่ยนแปลงตามข้อมูล Next.js รองรับ SSR เพื่อโหลด Meta Tags ตามเนื้อหาแต่ละหน้า

import Head from 'next/head';

export async function getServerSideProps() {
  const post = { title: "บทความสุดเจ๋ง!", description: "เนื้อหาดีมากเกี่ยวกับ SEO" };

  return { props: { post } };
}

export default function BlogPost({ post }) {
  return (
    <>
      <Head>
        <title>{post.title}</title>
        <meta name="description" content={post.description} />
      </Head>
      <main>
        <h1>{post.title}</h1>
        <p>{post.description}</p>
      </main>
    </>
  );
}

2️⃣ ใช้ Static Site Generation (SSG) ให้เว็บโหลดเร็ว

ถ้าเนื้อหาของเว็บเปลี่ยนไม่บ่อย เช่น หน้าเกี่ยวกับเรา หรือ หน้าผลิตภัณฑ์ เราสามารถใช้ SSG เพื่อให้เว็บโหลดเร็วขึ้น

export async function getStaticProps() {
  return {
    props: { title: "เกี่ยวกับเรา", description: "นี่คือหน้าเกี่ยวกับเรา" },
  };
}

🔍 เช็คว่า Meta Tags ทำงานหรือไม่?

หลังจากเพิ่ม Meta Tags แล้ว ต้องเช็คว่าใช้งานได้จริง โดยใช้เครื่องมือ

✅ Google Rich Results Test – https://search.google.com/test/rich-results
✅ Facebook Sharing Debugger – https://developers.facebook.com/tools/debug/
✅ Twitter Card Validator – https://cards-dev.twitter.com/validator


📌 สรุป

✅ ใช้ <Head> ใน Next.js เพื่อเพิ่ม Meta Tags
✅ เพิ่ม Open Graph Tags เพื่อให้ Social Media แสดงผลสวยๆ
✅ ใช้ Twitter Card Tags เพื่อให้เว็บดูดีเวลาทวีต
✅ ใช้ SSR และ SSG เพื่อปรับ Meta Tags ตามเนื้อหาแต่ละหน้า
✅ เช็คว่า Meta Tags ทำงานจริงผ่านเครื่องมือของ Google, Facebook และ Twitter

พร้อมทำ SEO ให้เว็บ Next.js ของคุณติดอันดับ Google แล้วหรือยัง? 🚀

วันพฤหัสบดีที่ 3 เมษายน พ.ศ. 2568

การใช้ Toast Notifications ใน Next.js: แจ้งเตือนแบบโปร ไม่ต้องรีโหลดหน้า

เคยเจอปัญหานี้ไหม? กดปุ่มแล้วไม่รู้ว่าระบบทำงานหรือยัง ส่งฟอร์มแล้วไม่แน่ใจว่าผ่านหรือไม่ หรืออยากให้เว็บมีแจ้งเตือนที่ดูดีแต่ไม่อยากเขียนเองให้ยุ่งยาก

วันนี้เราจะมาเรียนรู้วิธีใช้ Toast Notifications ใน Next.js แบบง่ายๆ โดยใช้ react-hot-toast ไลบรารีสุดเทพที่ช่วยให้แจ้งเตือนแบบลื่นไหล ดูดี และใช้งานง่าย

🔥 ทำไมต้องใช้ Toast Notifications?

Toast Notifications คือ ข้อความแจ้งเตือนแบบชั่วคราว ที่แสดงขึ้นมาในเว็บเมื่อมีเหตุการณ์บางอย่างเกิดขึ้น เช่น:

✅ แจ้งเตือนเมื่อทำรายการสำเร็จ ✅
✅ แจ้งเตือนข้อผิดพลาด (เช่น ฟอร์มไม่ถูกต้อง) ❌
✅ แจ้งเตือนระหว่างโหลดข้อมูล ⏳

Toast ดีๆ ควรเป็น Non-intrusive (ไม่รบกวน) และ Auto-dismiss (หายไปเอง) เพื่อไม่ให้ผู้ใช้รำคาญ

🚀 ติดตั้ง react-hot-toast ใน Next.js

เราจะใช้ react-hot-toast เพราะมันใช้ง่ายและทำงานได้ดีกับ Next.js

ติดตั้งแพ็กเกจ

npm install react-hot-toast

หรือถ้าใช้ Yarn

yarn add react-hot-toast


🎨 ตั้งค่า ToastProvider

ToastProvider เป็นคอมโพเนนต์ที่ช่วยให้เราสามารถใช้ toast ได้ทั่วแอป ต้องเพิ่มใน _app.js

แก้ไข pages/_app.js

import { Toaster } from 'react-hot-toast';
import '../styles/globals.css';

function MyApp({ Component, pageProps }) {
  return (
    <>
      <Toaster position="top-right" reverseOrder={false} />
      <Component {...pageProps} />
    </>
  );
}

export default MyApp;

🔹 position="top-right" – ให้ toast แสดงที่มุมขวาบน
🔹 reverseOrder={false} – ให้ข้อความใหม่ขึ้นด้านล่าง


🎯 ใช้งาน toast แจ้งเตือน

react-hot-toast ใช้งานง่ายมาก มีฟังก์ชันหลักๆ เช่น

  • toast.success("ข้อความ") ✅ แจ้งเตือนสำเร็จ
  • toast.error("ข้อความ") ❌ แจ้งเตือนข้อผิดพลาด
  • toast.loading("กำลังโหลด...") ⏳ แจ้งเตือนระหว่างโหลด
  • toast.dismiss() 🚫 ลบ toast ที่กำลังแสดง


💡 ตัวอย่างการใช้งาน toast ในปุ่ม

สร้างไฟล์ pages/index.js และเพิ่มปุ่มที่กดแล้วแจ้งเตือน

import toast from 'react-hot-toast';

export default function Home() {
  const notifySuccess = () => toast.success('บันทึกข้อมูลสำเร็จ! 🎉');
  const notifyError = () => toast.error('เกิดข้อผิดพลาด ❌');
  const notifyLoading = () => {
    const toastId = toast.loading('กำลังโหลดข้อมูล...');
    setTimeout(() => toast.success('โหลดสำเร็จ ✅', { id: toastId }), 2000);
  };

  return (
    <div className="p-10">
      <h1 className="text-2xl font-bold mb-4">🔔 ทดลองใช้ Toast Notifications</h1>
      <button onClick={notifySuccess} className="bg-green-500 text-white px-4 py-2 mr-2 rounded">✅ แจ้งเตือนสำเร็จ</button>
      <button onClick={notifyError} className="bg-red-500 text-white px-4 py-2 mr-2 rounded">❌ แจ้งเตือนข้อผิดพลาด</button>
      <button onClick={notifyLoading} className="bg-blue-500 text-white px-4 py-2 rounded">⏳ แจ้งเตือนระหว่างโหลด</button>
    </div>
  );
}

🔍 อธิบายโค้ด:

  • toast.success() ใช้แจ้งเตือนเมื่อทำรายการสำเร็จ
  • toast.error() ใช้แจ้งเตือนเมื่อเกิดข้อผิดพลาด
  • toast.loading() ใช้แจ้งเตือนว่ากำลังโหลดข้อมูล และอัปเดตเป็น toast.success() หลังจากโหลดเสร็จ


🎨 ปรับแต่งสไตล์ Toast

เราสามารถ กำหนดสไตล์ ของ toast ได้ เช่น เปลี่ยนสีพื้นหลัง เปลี่ยนไอคอน หรือกำหนดเวลาหายไปเอง

1️⃣ กำหนดเวลาให้ toast หายไปอัตโนมัติ

toast.success('บันทึกเรียบร้อย!', {
  duration: 5000, // แสดงผล 5 วินาที
});

2️⃣ เปลี่ยนสีและไอคอน

toast('🛑 คำเตือน: โปรดตรวจสอบข้อมูล', {
  style: {
    border: '1px solid red',
    padding: '16px',
    color: 'red',
  },
});

3️⃣ กำหนด animation

toast.success('ทำสำเร็จ!', {
  style: { animation: 'bounce 1s ease-in-out' },
});


🔄 ใช้ Toast กับ API Requests

ลองใช้ toast กับ API จริงๆ เช่น fetch()

const fetchData = async () => {
  const toastId = toast.loading('กำลังโหลดข้อมูล...');

  try {
    const response = await fetch('/api/data');
    const result = await response.json();

    toast.success('โหลดข้อมูลสำเร็จ!', { id: toastId });
  } catch (error) {
    toast.error('โหลดข้อมูลล้มเหลว', { id: toastId });
  }
};

🔍 อธิบาย:

  • toast.loading() แจ้งเตือนว่ากำลังโหลด
  • ถ้าโหลดสำเร็จ → toast.success()
  • ถ้าเกิดข้อผิดพลาด → toast.error()


📌 ใช้ Toast กับฟอร์ม

ในฟอร์มเราสามารถใช้ toast แจ้งเตือนว่า กรอกข้อมูลถูกต้องหรือไม่

const handleSubmit = (e) => {
  e.preventDefault();
 
  if (!email) {
    toast.error('กรุณากรอกอีเมล!');
    return;
  }

  toast.success('ส่งข้อมูลสำเร็จ!');
};

🏆 สรุป

✅ react-hot-toast ใช้งานง่ายมาก
✅ ใช้กับ API Requests, ฟอร์ม และปุ่มต่างๆ ได้
✅ ปรับแต่งสไตล์และอนิเมชันได้
✅ ไม่ต้องรีโหลดหน้า ก็แจ้งเตือนได้แบบสวยๆ

พร้อมใช้ Toast แจ้งเตือนให้เว็บของคุณดูโปรขึ้นหรือยัง? 🚀

วันพุธที่ 2 เมษายน พ.ศ. 2568

การสร้าง Dashboard UI ใน Next.js: ทำง่าย ใช้งานจริง แบบโปรๆ

เคยไหม? เวลาจะสร้าง Dashboard สวยๆ ในเว็บแอปพลิเคชันแต่ไม่รู้จะเริ่มตรงไหน? วันนี้เราจะมาลุยกันว่า Next.js จะช่วยให้เราสร้าง Dashboard UI ที่สวยงาม ใช้งานได้จริง และมีประสิทธิภาพได้ยังไง

🔥 ทำไมต้องใช้ Next.js สำหรับ Dashboard?

Next.js เป็นหนึ่งใน React Framework ที่เหมาะกับการสร้าง Dashboard มากๆ เพราะมันมีฟีเจอร์ที่ช่วยให้การพัฒนาเร็วขึ้น เช่น

✅ Server-side Rendering (SSR) – โหลดข้อมูลแบบเร็วจี๋ 🚀
✅ Static Site Generation (SSG) – ลดโหลดเซิร์ฟเวอร์และเพิ่มความเร็ว
✅ API Routes – จัดการข้อมูลจาก Backend ได้ในตัว
✅ การรองรับ Tailwind CSS, MUI, Ant Design – ทำ UI ได้ง่ายขึ้น

🛠️ เริ่มต้นโปรเจกต์ Dashboard ด้วย Next.js

1️⃣ ติดตั้ง Next.js

ถ้ายังไม่มีโปรเจกต์ Next.js ให้สร้างใหม่ก่อน

npx create-next-app@latest my-dashboard
cd my-dashboard
npm install

หรือถ้าใช้ Yarn

yarn create next-app my-dashboard
cd my-dashboard
yarn install

2️⃣ ติดตั้ง UI Library (Tailwind CSS หรือ MUI)

เราจะใช้ Tailwind CSS เพราะมันเบาและทำให้ดีไซน์ง่าย

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

แล้วเพิ่ม Tailwind ลงในไฟล์ tailwind.config.js

module.exports = {
  content: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {},
  },
  plugins: [],
};

จากนั้นใส่ Tailwind ลงใน styles/globals.css

@tailwind base;
@tailwind components;
@tailwind utilities;


🎨 สร้าง Layout หลักของ Dashboard

ปกติ Dashboard จะมี

✅ Sidebar
✅ Navbar
✅ Content Area

เราจะสร้าง Layout หลักที่ใช้ทั่วแอป

1️⃣ สร้างไฟล์ components/Layout.js

import Sidebar from './Sidebar';
import Navbar from './Navbar';

export default function Layout({ children }) {
  return (
    <div className="flex h-screen">
      <Sidebar />
      <div className="flex flex-col flex-1">
        <Navbar />
        <main className="p-4">{children}</main>
      </div>
    </div>
  );
}

2️⃣ สร้าง Sidebar (components/Sidebar.js)

import Link from 'next/link';

export default function Sidebar() {
  return (
    <div className="w-64 bg-gray-800 text-white h-screen p-5">
      <h2 className="text-xl font-bold mb-5">Dashboard</h2>
      <ul>
        <li className="mb-2">
          <Link href="/" className="block p-2 hover:bg-gray-700 rounded">🏠 หน้าหลัก</Link>
        </li>
        <li className="mb-2">
          <Link href="/analytics" className="block p-2 hover:bg-gray-700 rounded">📊 Analytics</Link>
        </li>
        <li className="mb-2">
          <Link href="/settings" className="block p-2 hover:bg-gray-700 rounded">⚙️ Settings</Link>
        </li>
      </ul>
    </div>
  );
}

3️⃣ สร้าง Navbar (components/Navbar.js)

export default function Navbar() {
  return (
    <div className="bg-white shadow-md p-4 flex justify-between">
      <h1 className="text-lg font-bold">Dashboard</h1>
      <div>👤 User</div>
    </div>
  );
}


4️⃣ ใช้ Layout ในหน้า pages/_app.js

import Layout from '../components/Layout';
import '../styles/globals.css';

function MyApp({ Component, pageProps }) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}

export default MyApp;


📊 สร้างหน้า Dashboard พร้อมกราฟ

ใน Dashboard จริงๆ มักจะมี กราฟ และ ตารางข้อมูล เราจะใช้ Recharts เพื่อแสดงกราฟ

1️⃣ ติดตั้ง Recharts

npm install recharts


2️⃣ สร้างหน้า pages/index.js

import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';

const data = [
  { month: 'Jan', sales: 4000 },
  { month: 'Feb', sales: 3000 },
  { month: 'Mar', sales: 5000 },
  { month: 'Apr', sales: 7000 },
];

export default function Dashboard() {
  return (
    <div>
      <h1 className="text-2xl font-bold mb-4">📈 สถิติยอดขาย</h1>
      <div className="bg-white p-4 shadow-md">
        <ResponsiveContainer width="100%" height={300}>
          <LineChart data={data}>
            <XAxis dataKey="month" />
            <YAxis />
            <Tooltip />
            <Line type="monotone" dataKey="sales" stroke="#8884d8" strokeWidth={2} />
          </LineChart>
        </ResponsiveContainer>
      </div>
    </div>
  );
}


📌 เพิ่มตารางข้อมูล

เราจะใช้ TanStack Table เพื่อแสดงข้อมูลในรูปแบบตาราง

1️⃣ ติดตั้ง TanStack Table

npm install @tanstack/react-table

2️⃣ เพิ่มตารางใน pages/index.js

import { useReactTable, getCoreRowModel, flexRender } from '@tanstack/react-table';

const data = [
  { id: 1, name: 'John Doe', role: 'Admin' },
  { id: 2, name: 'Jane Smith', role: 'Editor' },
];

const columns = [
  { accessorKey: 'id', header: 'ID' },
  { accessorKey: 'name', header: 'ชื่อ' },
  { accessorKey: 'role', header: 'บทบาท' },
];

export default function Dashboard() {
  const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel() });

  return (
    <div>
      <h1 className="text-2xl font-bold mb-4">👥 ผู้ใช้งาน</h1>
      <table className="border-collapse border border-gray-300 w-full">
        <thead>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => (
                <th key={header.id} className="border p-2 bg-gray-100">
                  {flexRender(header.column.columnDef.header, header.getContext())}
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody>
          {table.getRowModel().rows.map((row) => (
            <tr key={row.id}>
              {row.getVisibleCells().map((cell) => (
                <td key={cell.id} className="border p-2">
                  {flexRender(cell.column.columnDef.cell, cell.getContext())}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

🎯 สรุป

✅ สร้าง Dashboard UI ใน Next.js ได้ง่าย
✅ ใช้ Tailwind CSS ทำให้ UI สวยแบบไม่ต้องเขียน CSS เอง
✅ ใช้ Recharts และ TanStack Table เพื่อแสดงข้อมูลได้อย่างมืออาชีพ

พร้อมสร้าง Dashboard ของคุณเองแล้วหรือยัง?

วันอังคารที่ 1 เมษายน พ.ศ. 2568

การแสดงผลตารางใน Next.js ด้วย TanStack Table: ง่าย สวย และยืดหยุ่นสุดๆ

ถ้าคุณเคยต้องทำตารางใน React หรือ Next.js แล้วรู้สึกว่ามันยุ่งยากไปหมด ไม่ว่าจะเป็นการจัดการข้อมูล การกรอง (filtering) การเรียงลำดับ (sorting) หรือการแบ่งหน้า (pagination) วันนี้เราจะมาแนะนำ TanStack Table (หรือชื่อเดิมคือ React Table) ที่จะช่วยให้คุณสร้างตารางขั้นเทพได้แบบง่ายๆ

ทำไมต้องใช้ TanStack Table?

ในโปรเจกต์ที่ต้องแสดงข้อมูลในรูปแบบตาราง เช่น รายการคำสั่งซื้อ, รายการผู้ใช้ หรือข้อมูลสถิติต่างๆ เราต้องการฟีเจอร์พวกนี้:

✅ การจัดการข้อมูลที่ยืดหยุ่น (เช่น ใช้ API ดึงข้อมูลมาแสดง)
✅ Sorting, Filtering, และ Pagination แบบไม่ต้องเขียนเอง
✅ รองรับการใช้งานกับ Next.js และ SSR (Server-side Rendering)

TanStack Table ทำได้หมด! 🎉

ติดตั้ง TanStack Table

ก่อนอื่น เราต้องติดตั้งไลบรารีก่อน

npm install @tanstack/react-table

หรือถ้าใช้ Yarn

yarn add @tanstack/react-table


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

มาลองสร้างตารางง่ายๆ กันก่อน โดยใช้ข้อมูลแบบ static

1. ตั้งค่าข้อมูลและคอลัมน์

const data = [
  { id: 1, name: 'John Doe', age: 28, email: 'john@example.com' },
  { id: 2, name: 'Jane Smith', age: 32, email: 'jane@example.com' },
  { id: 3, name: 'Bob Brown', age: 24, email: 'bob@example.com' },
];

const columns = [
  { accessorKey: 'id', header: 'ID' },
  { accessorKey: 'name', header: 'ชื่อ' },
  { accessorKey: 'age', header: 'อายุ' },
  { accessorKey: 'email', header: 'อีเมล' },
];

อธิบาย:

  • data คือข้อมูลที่เราจะเอามาแสดง
  • columns กำหนดโครงสร้างของตาราง ใช้ accessorKey เพื่อระบุคีย์ของข้อมูล


2. ใช้ TanStack Table เพื่อแสดงตาราง

import { useReactTable, getCoreRowModel, flexRender } from '@tanstack/react-table';

export default function MyTable() {
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
  });

  return (
    <table border="1">
      <thead>
        {table.getHeaderGroups().map((headerGroup) => (
          <tr key={headerGroup.id}>
            {headerGroup.headers.map((header) => (
              <th key={header.id}>{flexRender(header.column.columnDef.header, header.getContext())}</th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody>
        {table.getRowModel().rows.map((row) => (
          <tr key={row.id}>
            {row.getVisibleCells().map((cell) => (
              <td key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
}

สรุปโค้ด:

  • useReactTable() ใช้สร้างตารางจาก data และ columns
  • getCoreRowModel() ใช้เพื่อจัดการโครงสร้างของข้อมูล
  • flexRender() ช่วยให้เราสามารถเรนเดอร์ค่าที่กำหนดใน columns ได้


เพิ่ม Sorting (เรียงลำดับ)

ถ้าอยากให้ตารางสามารถเรียงลำดับ (sorting) ได้ ให้เพิ่ม getSortedRowModel()

import { useReactTable, getCoreRowModel, getSortedRowModel, flexRender } from '@tanstack/react-table';

export default function MyTable() {
  const [sorting, setSorting] = React.useState([]);
 
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    onSortingChange: setSorting,
    state: { sorting },
  });

  return (
    <table border="1">
      <thead>
        {table.getHeaderGroups().map((headerGroup) => (
          <tr key={headerGroup.id}>
            {headerGroup.headers.map((header) => (
              <th key={header.id} onClick={() => header.column.getToggleSortingHandler()?.()}>
                {flexRender(header.column.columnDef.header, header.getContext())}
                {header.column.getIsSorted() === 'asc' ? ' 🔼' : header.column.getIsSorted() === 'desc' ? ' 🔽' : ''}
              </th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody>
        {table.getRowModel().rows.map((row) => (
          <tr key={row.id}>
            {row.getVisibleCells().map((cell) => (
              <td key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
}

ตอนนี้เราสามารถคลิกที่หัวตารางเพื่อเรียงข้อมูลได้แล้ว! 🎉


เพิ่ม Pagination (แบ่งหน้า)

ถ้าข้อมูลเยอะๆ เราอาจต้องการ pagination เพื่อให้ผู้ใช้สามารถเลื่อนดูหน้าอื่นๆ ได้

import { useReactTable, getCoreRowModel, getPaginationRowModel, flexRender } from '@tanstack/react-table';

export default function MyTable() {
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
  });

  return (
    <div>
      <table border="1">
        <thead>
          {table.getHeaderGroups().map((headerGroup) => (
            <tr key={headerGroup.id}>
              {headerGroup.headers.map((header) => (
                <th key={header.id}>{flexRender(header.column.columnDef.header, header.getContext())}</th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody>
          {table.getRowModel().rows.map((row) => (
            <tr key={row.id}>
              {row.getVisibleCells().map((cell) => (
                <td key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
      <div>
        <button onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}>
          ก่อนหน้า
        </button>
        <span> หน้า {table.getState().pagination.pageIndex + 1} </span>
        <button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
          ถัดไป
        </button>
      </div>
    </div>
  );
}


สรุป

✅ TanStack Table ช่วยให้สร้างตารางใน Next.js ได้ง่ายและยืดหยุ่น
✅ รองรับ Sorting, Pagination, Filtering
✅ ทำงานได้ดีทั้ง Client-side และ Server-side Rendering

ถ้าคุณต้องการตารางที่เร็วและยืดหยุ่น TanStack Table คือตัวเลือกที่ดีสุด! 

วันจันทร์ที่ 31 มีนาคม พ.ศ. 2568

การจัดการฟอร์มใน Next.js ด้วย React Hook Form: ใช้ง่าย ประหยัดแรง

ถ้าพูดถึงการจัดการฟอร์มใน React หรือ Next.js หลายคนคงเคยเจอปัญหาปวดหัวกับการจัดการ state, validation, และการ submit ข้อมูลกันใช่ไหม? วันนี้เราจะมาทำความรู้จักกับ React Hook Form ซึ่งเป็นหนึ่งในไลบรารีจัดการฟอร์มที่ดีที่สุดสำหรับ React และ Next.js ทำให้ชีวิตนักพัฒนาง่ายขึ้นเยอะ!

ทำไมต้องใช้ React Hook Form?

โดยปกติ ถ้าเราจัดการฟอร์มใน React ด้วย useState() เราจะต้องสร้าง state แยกกันตามฟิลด์ของฟอร์ม เช่น

const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

แล้วทุกครั้งที่มีการเปลี่ยนค่าฟิลด์ เราต้องใช้ onChange มาจับข้อมูลอีก

<input type="text" value={name} onChange={(e) => setName(e.target.value)} />

มันใช้ได้ก็จริง แต่มันเยอะและยุ่งยาก!

React Hook Form (RHF) ช่วยลดความยุ่งยากนี้ ด้วยการทำให้ฟอร์มเป็นแบบ uncontrolled ซึ่งหมายความว่า ไม่ต้องใช้ useState() คุมค่าฟิลด์แบบ manual แต่ให้ React ทำงานร่วมกับ DOM โดยตรง

ติดตั้ง React Hook Form

ก่อนอื่น ต้องติดตั้ง React Hook Form ก่อน

npm install react-hook-form

หรือถ้าใช้ Yarn

yarn add react-hook-form


ใช้ React Hook Form ใน Next.js

มาดูโค้ดตัวอย่างง่ายๆ ของการใช้งาน React Hook Form ใน Next.js

สร้างฟอร์มแบบง่าย

import { useForm } from 'react-hook-form';

export default function MyForm() {
  const { register, handleSubmit } = useForm();

  const onSubmit = (data) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('name')} placeholder="ชื่อ" />
      <input {...register('email')} type="email" placeholder="อีเมล" />
      <button type="submit">ส่ง</button>
    </form>
  );
}

อธิบายโค้ด:

  • useForm() คือฟังก์ชันหลักที่ใช้ดึง API ต่างๆ
  • register() ใช้สำหรับเชื่อมโยงอินพุตฟอร์มกับ React Hook Form
  • handleSubmit(onSubmit) ใช้จัดการการส่งฟอร์ม
  • data ที่ได้จาก onSubmit() จะเป็นอ็อบเจ็กต์ที่รวมค่าทั้งหมดในฟอร์ม


การเพิ่ม Validation

ถ้าไม่อยากให้ผู้ใช้กรอกมั่วๆ ก็ต้องเพิ่ม Validation Rules เข้าไป โดยใช้ register()

import { useForm } from 'react-hook-form';

export default function MyForm() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm();

  const onSubmit = (data) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('name', { required: 'ต้องกรอกชื่อ' })} placeholder="ชื่อ" />
      {errors.name && <p>{errors.name.message}</p>}

      <input {...register('email', { required: 'ต้องกรอกอีเมล', pattern: { value: /\S+@\S+\.\S+/, message: 'รูปแบบอีเมลไม่ถูกต้อง' } })} placeholder="อีเมล" />
      {errors.email && <p>{errors.email.message}</p>}

      <button type="submit">ส่ง</button>
    </form>
  );
}

สิ่งที่เพิ่มเข้ามา:

  • ใช้ errors เพื่อตรวจจับข้อผิดพลาดในแต่ละฟิลด์
  • ถ้ามี error จะแสดงข้อความแจ้งเตือนใต้ input


การใช้ Default Values

บางครั้งเราอาจต้องกำหนดค่าตั้งต้นให้ฟอร์ม เช่น กรณีแก้ไขข้อมูลผู้ใช้

const { register, handleSubmit } = useForm({
  defaultValues: {
    name: 'John Doe',
    email: 'john@example.com',
  },
});


ใช้ Controller กับ React Hook Form

ถ้าเราต้องใช้ React Component ของบุคคลที่สาม (เช่น React Select หรือ DatePicker) ที่ไม่รองรับ register() โดยตรง เราต้องใช้ Controller

import { useForm, Controller } from 'react-hook-form';
import Select from 'react-select';

export default function MyForm() {
  const { control, handleSubmit } = useForm();

  const onSubmit = (data) => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="gender"
        control={control}
        render={({ field }) => <Select {...field} options={[{ label: 'ชาย', value: 'male' }, { label: 'หญิง', value: 'female' }]} />}
      />
      <button type="submit">ส่ง</button>
    </form>
  );
}

ใช้งานร่วมกับ Next.js API Routes

ถ้าเราต้องการส่งข้อมูลไปที่ API ใน Next.js สามารถทำแบบนี้

const onSubmit = async (data) => {
  const response = await fetch('/api/submit', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  });
  const result = await response.json();
  console.log(result);
};

ฝั่ง API Route (/pages/api/submit.js)

export default function handler(req, res) {
  if (req.method === 'POST') {
    res.status(200).json({ message: 'ฟอร์มถูกส่งแล้ว!', data: req.body });
  } else {
    res.status(405).json({ message: 'Method Not Allowed' });
  }
}

สรุป

React Hook Form เป็นตัวช่วยที่ทำให้การจัดการฟอร์มใน Next.js ง่ายขึ้น ลดโค้ดที่ต้องเขียน และรองรับ validation แบบ built-in

  • ใช้งานง่าย – ใช้ register() เชื่อมโยงฟิลด์ได้เลย
  • ไม่ต้องใช้ useState() แยกฟิลด์ – ประหยัดโค้ด
  • รองรับ validation ในตัว – กำหนดเงื่อนไขได้ง่าย
  • ทำงานเร็วกว่าโซลูชันอื่นๆ เช่น Formik

ถ้าคุณต้องการจัดการฟอร์มใน Next.js React Hook Form คือคำตอบ!

วันอาทิตย์ที่ 30 มีนาคม พ.ศ. 2568

การใช้ Zustand หรือ Redux ใน Next.js: อะไรดีกว่ากัน?

ถ้าพูดถึงการจัดการ state ใน Next.js เชื่อว่าหลายคนต้องเคยลังเลระหว่าง Zustand กับ Redux แน่นอน เพราะทั้งสองตัวนี้ได้รับความนิยมมากและมีแนวทางการทำงานที่แตกต่างกัน วันนี้เราจะมาคุยกันแบบบ้านๆ ไม่เน้นทฤษฎีเยอะ แต่เน้นให้เข้าใจง่าย ว่าควรเลือกใช้ตัวไหนดีสำหรับโปรเจกต์ของคุณ

ทำไมต้องจัดการ State ใน Next.js?

Next.js เป็น React Framework ที่ช่วยให้เราสร้างเว็บแอปพลิเคชันได้เร็วและดีขึ้น แต่ถึงจะเทพแค่ไหน Next.js ก็ยังมีปัญหาเรื่องการจัดการ state ที่เราต้องคิดหนัก โดยเฉพาะเมื่อเว็บของเรามีหลายหน้า (multi-page) หรือมีข้อมูลที่แชร์กันระหว่างคอมโพเนนต์หลายตัว

ในกรณีที่ state ของเราซับซ้อนขึ้น การใช้ useState() หรือ useContext() อาจจะไม่พอแล้ว เช่น

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

ถึงจุดนี้แหละ ที่พวก State Management Library อย่าง Zustand และ Redux โผล่มาช่วยชีวิตเรา

Redux: เจ้าพ่อ State Management

จุดเด่นของ Redux

Redux เป็น state container ระดับตำนานที่อยู่กับ React มานาน มันใช้ single source of truth (เก็บ state ไว้ที่เดียว) และเปลี่ยนค่า state ด้วย action และ reducer

สิ่งที่ทำให้ Redux เจ๋งคือ

  • Predictable State – ทุกการเปลี่ยนแปลงของ state ถูกควบคุมโดย action และ reducer ทำให้ debug ง่าย
  • DevTools สุดเทพ – มี Redux DevTools ให้ตรวจสอบทุกการเปลี่ยนแปลงของ state ได้แบบ real-time
  • Ecosystem ใหญ่โต – มี middleware อย่าง Redux Thunk หรือ Redux Saga ช่วยให้จัดการ asynchronous action ได้ง่ายขึ้น


จุดด้อยของ Redux

  • โค้ดยาว – Redux ต้องสร้าง action, reducer และ dispatch ซึ่งทำให้โค้ดยืดยาว ถ้าทำผิดที่เดียวอาจล้มทั้งระบบ
  • ต้องใช้ boilerplate เยอะ – แค่จะอัพเดท state ต้องผ่านหลายขั้นตอน เช่น สร้าง action → dispatch action → reducer → update store
  • Learning Curve สูง – สำหรับมือใหม่ Redux อาจทำให้ปวดหัว เพราะต้องเข้าใจโครงสร้างหลายอย่าง



Zustand: เบา สั้น และเร็ว

จุดเด่นของ Zustand

Zustand เป็น state management ที่เบาและง่ายกว่า Redux มันใช้แนวคิดของ flux pattern แต่ไม่ต้องมี action หรือ reducer ให้วุ่นวาย

สิ่งที่ทำให้ Zustand น่าสนใจคือ

  • API ใช้ง่าย – ไม่ต้องมี action หรือ reducer แค่สร้าง store แล้วใช้ได้เลย
  • ไม่มี boilerplate – Zustand ใช้ฟังก์ชันเดียวสร้าง state ได้ทันที
  • ใช้งานร่วมกับ Server Components ได้ดี – ทำให้เหมาะกับ Next.js ที่ใช้ App Router


จุดด้อยของ Zustand

  • ไม่มี DevTools ที่เทพเท่า Redux – ถ้าต้องการ debug อาจต้องใช้ console.log แทน
  • เหมาะกับโปรเจกต์ขนาดกลาง-เล็ก – ถ้าเป็นแอปขนาดใหญ่ Redux อาจจะควบคุม state ได้ดีกว่า





เปรียบเทียบ Redux vs Zustand

Feature Redux Zustand
โครงสร้างโค้ด ซับซ้อน ต้องมี action, reducer, store เรียบง่าย ใช้ฟังก์ชันเดียวสร้าง store
Performance อาจมี overhead สูงถ้าใช้ไม่ดี เบาและเร็วกว่า Redux
DevTools Redux DevTools ช่วย debug ได้ดี มี DevTools แต่ไม่เทพเท่า Redux
การใช้งานกับ Next.js ต้อง config เพิ่ม ใช้งานง่าย ไม่มี config ยุ่งยาก
เหมาะกับโปรเจกต์ ใหญ่และซับซ้อน เล็ก-กลาง


ควรใช้ Zustand หรือ Redux ใน Next.js?

ใช้ Redux ถ้า

✅ โปรเจกต์ของคุณ ซับซ้อน และต้องจัดการ state เยอะ
✅ ต้องการ DevTools เพื่อ debug state ได้ง่าย
✅ แอปของคุณต้องการ middleware เช่น Redux Thunk หรือ Redux Saga

ใช้ Zustand ถ้า

✅ คุณต้องการโค้ดที่ เรียบง่าย และ ไม่ต้องการ boilerplate
✅ โปรเจกต์ของคุณเป็น ขนาดเล็ก-กลาง และไม่ต้องการ state management ที่หนัก
✅ คุณใช้ Next.js App Router และต้องการ state management ที่เข้ากันได้ดี


ตัวอย่างการใช้ Redux กับ Next.js

ก่อนจะใช้ Redux กับ Next.js ต้องติดตั้งแพ็กเกจก่อน

npm install @reduxjs/toolkit react-redux

จากนั้นสร้าง store.js

import { configureStore, createSlice } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: (state) => { state.value += 1; },
    decrement: (state) => { state.value -= 1; },
  },
});

export const { increment, decrement } = counterSlice.actions;

export const store = configureStore({
  reducer: {
    counter: counterSlice.reducer,
  },
});

แล้วใช้ Provider ใน _app.js หรือ layout.js

import { Provider } from 'react-redux';
import { store } from '../store';

export default function App({ Component, pageProps }) {
  return (
    <Provider store={store}>
      <Component {...pageProps} />
    </Provider>
  );
}

ดึงค่า state ไปใช้ในคอมโพเนนต์

import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement } from '../store';

export default function Counter() {
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => dispatch(increment())}>+</button>
      <button onClick={() => dispatch(decrement())}>-</button>
    </div>
  );
}

ตัวอย่างการใช้ Zustand กับ Next.js

ติดตั้ง Zustand ก่อน

npm install zustand

สร้าง store.js

import { create } from 'zustand';

const useCounterStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}));

export default useCounterStore;

ใช้ในคอมโพเนนต์

import useCounterStore from '../store';

export default function Counter() {
  const { count, increment, decrement } = useCounterStore();

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
    </div>
  );
}

สรุป

  • Redux เหมาะกับโปรเจกต์ขนาดใหญ่ที่ต้องการความเป็นระบบ
  • Zustand เหมาะกับโปรเจกต์ที่ต้องการความง่ายและเร็ว
  • ถ้าคุณไม่แน่ใจ ให้ลองใช้ Zustand ก่อน ถ้ารู้สึกว่าไม่พอ ค่อยย้ายไป Redux

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

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

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