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

วันเสาร์ที่ 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 เลย! 🚀

วันพฤหัสบดีที่ 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 คือตัวเลือกที่ดีสุด! 

วันเสาร์ที่ 22 กุมภาพันธ์ พ.ศ. 2568

การใช้ CSS ใน Next.js (CSS Modules และ Global CSS)

Next.js เป็นหนึ่งในเฟรมเวิร์กยอดฮิตสำหรับการสร้างเว็บแอปพลิเคชันด้วย React ซึ่งแน่นอนว่าเรื่องของการสไตลิ่ง (styling) ก็เป็นส่วนสำคัญที่เราต้องจัดการให้ดี ใน Next.js เรามีหลายทางเลือกในการใช้ CSS และที่นิยมกันมากคือ CSS Modules และ Global CSS วันนี้เราจะมาทำความเข้าใจทั้งสองแนวทางนี้กันแบบเข้าใจง่าย ๆ

🌍 Global CSS: สไตล์แบบจัดเต็มทั้งเว็บ

Global CSS คือการใช้ไฟล์ CSS ทั่วไปที่เราคุ้นเคยกันดี เหมือนที่ใช้ใน HTML หรือ React ปกติ วิธีนี้เหมาะกับการกำหนดสไตล์ที่ใช้ซ้ำกันทั้งเว็บ เช่น ฟอนต์ พื้นหลัง หรือธีมหลัก

🛠 วิธีใช้ Global CSS ใน Next.js

1. สร้างไฟล์ CSS
    โดยทั่วไป เราจะเก็บไฟล์ Global CSS ไว้ที่ styles/global.css

2. นำเข้าใน _app.js หรือ _app.tsx
    _app.js เป็นไฟล์หลักที่ใช้ควบคุมแอปทั้งหมด ดังนั้นถ้าเราต้องการให้ Global CSS ใช้งานได้ทุกหน้าก็ต้อง import เข้าไปในไฟล์นี้

import '../styles/global.css';

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

export default MyApp;

3. ใช้งานได้เลย!
    ตอนนี้เราสามารถเขียน CSS ตามปกติใน global.css ได้ เช่น

    body {
      font-family: 'Arial', sans-serif;
      background-color: #f5f5f5;
    }

    h1 {
      color: blue;
    }

❌ ข้อควรระวัง

  • Global CSS มีผลต่อทุกหน้า
  • ถ้าเผลอไปกำหนดสไตล์ผิด ๆ อาจจะพังทั้งเว็บ!
  • ไม่สามารถใช้ CSS Modules ใน _app.js ได้
  • Next.js ไม่อนุญาตให้ import CSS Modules ใน _app.js ต้องใช้ Global CSS เท่านั้น


🎯 CSS Modules: สไตล์แบบแยกเฉพาะตัว

CSS Modules เป็นเทคนิคที่ทำให้ CSS มีขอบเขตเฉพาะคอมโพเนนต์ ไม่ต้องกลัวปัญหา CSS ซ้อนทับกัน หรือไปยุ่งกับสไตล์ของส่วนอื่นในเว็บ

🛠 วิธีใช้ CSS Modules ใน Next.js

1. สร้างไฟล์ CSS Modules
    ไฟล์ CSS Modules จะต้องลงท้ายด้วย .module.css เช่น styles/Button.module.css

2. นำเข้าในคอมโพเนนต์

import styles from '../styles/Button.module.css';

function Button() {
  return <button className={styles.button}>คลิกเลย!</button>;
}

export default Button;

3. เขียนสไตล์ในไฟล์ CSS Modules

    /* styles/Button.module.css */
    .button {
      background-color: #ff6347;
      color: white;
      padding: 10px 20px;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }

✅ ข้อดีของ CSS Modules

  • ไม่มีปัญหา CSS ซ้อนทับกัน เพราะทุกคลาสจะถูกทำให้มีชื่อเฉพาะตัว เช่น Button_button__3fXj9
  • แยกสไตล์แต่ละคอมโพเนนต์ได้ง่าย ทำให้โค้ดดูแลรักษาง่ายขึ้น
  • สามารถใช้ร่วมกับ SCSS ได้ ถ้าต้องการใช้ SCSS ก็แค่เปลี่ยนนามสกุลไฟล์เป็น .module.scss แล้วติดตั้ง sass

    npm install sass


🤔 เลือกใช้ Global CSS หรือ CSS Modules ดี?

วิธี ข้อดี ข้อเสีย
Global CSS ใช้งานง่าย, ใช้กับธีมและสไตล์ทั่วเว็บได้ อาจเกิดปัญหา CSS ซ้อนกัน
CSS Modules ป้องกัน CSS ทับกัน, เหมาะกับคอมโพเนนต์แยกกัน ใช้กับ _app.js ไม่ได้

🔥 ใช้ร่วมกันได้!

จริง ๆ แล้ว เราสามารถใช้ Global CSS สำหรับธีมหลัก และใช้ CSS Modules สำหรับคอมโพเนนต์เฉพาะตัวได้ โดยไม่ต้องเลือกอย่างใดอย่างหนึ่ง


💡 เทคนิคน่าสนใจ

ใช้ CSS Modules ร่วมกับ classnames

ถ้าอยากใช้หลายคลาสพร้อมกันใน CSS Modules ลองใช้ไลบรารี classnames

npm install classnames

แล้วใช้แบบนี้ในคอมโพเนนต์:

import styles from '../styles/Card.module.css';
import classNames from 'classnames';

function Card({ highlighted }) {
  return (
    <div className={classNames(styles.card, { [styles.highlighted]: highlighted })}>
      นี่คือการ์ด!
    </div>
  );
}

export default Card;

/* styles/Card.module.css */
.card {
  padding: 20px;
  border: 1px solid #ddd;
}

.highlighted {
  background-color: yellow;
}


🔥 สรุป

  • Global CSS ใช้สำหรับธีมหลักของเว็บ
  • CSS Modules เหมาะกับสไตล์ที่ต้องการแยกเฉพาะคอมโพเนนต์
  • สามารถใช้ Global CSS และ CSS Modules ร่วมกันได้
  • ถ้าต้องการใช้หลายคลาสใน CSS Modules ให้ใช้ classnames

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

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

การสร้าง Component และการนำไปใช้ใน Next.js

ถ้าคุณเป็นสาย React และกำลังใช้ Next.js เพื่อสร้างเว็บแอป คุณอาจสงสัยว่า "การสร้าง Component และนำไปใช้ใน Next.js ต่างจาก React ปกติยังไง?"

จริง ๆ แล้วหลักการสร้าง Component ใน Next.js ก็คล้ายกับ React ทั่วไป แต่ Next.js มีฟีเจอร์พิเศษบางอย่างที่ช่วยให้การจัดการ Component มีประสิทธิภาพขึ้น

บทความนี้จะพาคุณไปดูทุกมุมของการสร้าง Component ตั้งแต่พื้นฐาน ไปจนถึงแนวทางปฏิบัติที่ดี เพื่อให้คุณสามารถ เขียนโค้ดที่เป็นระเบียบ ใช้ซ้ำได้ และโหลดเร็วขึ้น

Component คืออะไร?

Component เป็นส่วนย่อยของ UI ที่สามารถนำมาใช้ซ้ำได้ ตัวอย่างเช่น

  • ปุ่ม (Button)
  • แถบนำทาง (Navbar)
  • การ์ดแสดงข้อมูล (Card)
  • กล่องข้อความ (Input field)

แทนที่เราจะเขียนโค้ดซ้ำ ๆ ทุกหน้า เราสามารถสร้าง Component และนำไปใช้ซ้ำได้ทั่วทั้งเว็บ

1. การสร้าง Component ใน Next.js

1.1 การสร้าง Component แบบพื้นฐาน

ใน Next.js ไฟล์ Component ควรเก็บไว้ในโฟลเดอร์ components/ เพื่อให้โครงสร้างโปรเจกต์ดูเป็นระเบียบ

ตัวอย่างการสร้าง Component Button.js

export default function Button({ text }) {
  return <button className="btn">{text}</button>;
}


Note:

  • เราส่งค่า text ผ่าน Props เพื่อให้ปุ่มนี้สามารถแสดงข้อความที่แตกต่างกันได้
  • ควรตั้งชื่อไฟล์เป็น ตัวพิมพ์ใหญ่ เช่น Button.js ตามหลักการตั้งชื่อ Component

 

1.2 การใช้ Component ในหน้า Next.js

เมื่อสร้าง Component แล้ว เราสามารถ import และใช้มันในไฟล์อื่น ได้ เช่นใน pages/index.js

ใช้ Button ในหน้า index.js

import Button from '../components/Button';

export default function Home() {
  return (
    <div>
      <h1>Welcome to Next.js 🚀</h1>
      <Button text="คลิกเลย!" />
      <Button text="สมัครสมาชิก" />
    </div>
  );
}

✅ ผลลัพธ์ที่ได้:

Welcome to Next.js 🚀  
[ คลิกเลย! ]  [ สมัครสมาชิก ]

1.3 การส่งค่า Props ไปยัง Component

Props เป็นค่าที่ส่งจาก Parent Component ไปยัง Child Component
ทำให้เราสามารถปรับแต่ง Component ได้ง่ายขึ้น

ตัวอย่าง Component Card.js รับค่า Props

export default function Card({ title, description }) {
  return (
    <div className="card">
      <h2>{title}</h2>
      <p>{description}</p>
    </div>
  );
}


การใช้ Card ใน index.js


import Card from '../components/Card';

export default function Home() {
  return (
    <div>
      <h1>รายการบทความ</h1>
      <Card title="Next.js คืออะไร?" description="Next.js เป็น React Framework ที่ได้รับความนิยมมาก" />
      <Card title="การใช้ API Routes" description="API Routes ช่วยให้เราสร้าง Backend ใน Next.js ได้ง่าย" />
    </div>
  );
}


✅ ผลลัพธ์ที่ได้:

รายการบทความ  
----------------  
Next.js คืออะไร?  
Next.js เป็น React Framework ที่ได้รับความนิยมมาก  

การใช้ API Routes  
API Routes ช่วยให้เราสร้าง Backend ใน Next.js ได้ง่าย  


สังเกต:

  • เราสามารถใช้ Card ได้หลายครั้งโดยเปลี่ยนค่า Props
  • ทำให้โค้ดดูสะอาด และจัดการง่ายขึ้น


2. การจัดการ Layout ด้วย Component

Next.js มีไฟล์ _app.js ซึ่งช่วยให้เราสร้าง Layout ที่ใช้ซ้ำกันทุกหน้า ได้ง่ายขึ้น

2.1 สร้าง Layout Component

ไฟล์ components/Layout.js

export default function Layout({ children }) {
  return (
    <div>
      <header>🔥 My Website</header>
      <main>{children}</main>
      <footer>⚡ Powered by Next.js</footer>
    </div>
  );
}


2.2 ใช้ Layout ใน _app.js

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

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

✅ ผลลัพธ์ที่ได้

  • ทุกหน้าจะมี Header และ Footer โดยอัตโนมัติ



3. การใช้ CSS ใน Component

Next.js รองรับการใช้ CSS ได้หลายแบบ เช่น

  •     Global CSS (styles/globals.css)
  •     Module CSS (.module.css)
  •     Styled Components


3.1 ใช้ Global CSS

ไฟล์: styles/globals.css

.btn {
  background-color: blue;
  color: white;
  padding: 10px 20px;
  border: none;
  cursor: pointer;
}

ไฟล์: components/Button.js

import '../styles/globals.css';

export default function Button({ text }) {
  return <button className="btn">{text}</button>;
}


✅ ข้อดีของ Global CSS

  •     ใช้งานง่าย และใช้ได้กับทุก Component


3.2 ใช้ Module CSS (แนะนำ)

ไฟล์: components/Button.module.css

.btn {
  background-color: red;
  color: white;
  padding: 10px 20px;
  border: none;
  cursor: pointer;
}

ไฟล์: components/Button.js

import styles from './Button.module.css';

export default function Button({ text }) {
  return <button className={styles.btn}>{text}</button>;
}


✅ ข้อดีของ Module CSS

  • ป้องกันการชนกันของ CSS
  • ทำให้โค้ดเป็นระเบียบ

สรุป

หัวข้อวิธีใช้งาน
สร้าง Componentใช้ Function Component (export default function Component() {})
ใช้ Componentimport Component from '../components/Component'
ส่งค่าเข้า Componentใช้ Props (<Component name="John" />)
ใช้ Layout ซ้ำกันทุกหน้าใช้ _app.js และ Layout Component
ใช้ CSS ใน Componentใช้ Global CSS หรือ Module CSS


ข้อดีของการใช้ Component ใน Next.js
✅ โค้ดสะอาดขึ้น
✅ ใช้ซ้ำได้
✅ โหลดเร็วขึ้น (Static Optimization)

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

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