คอมโพเนนต์ฝั่งเซิร์ฟเวอร์กับฝั่งไคลเอ็นต์ใน Next.js
ตัดสินใจว่าจะเพิ่ม 'use client' เมื่อใด และประกอบโครงสร้างฝั่งเซิร์ฟเวอร์กับฝั่งไคลเอ็นต์อย่างไร
คอมโพเนนต์ฝั่งเซิร์ฟเวอร์กับฝั่งไคลเอ็นต์ใน Next.js เป็นบทเรียน React Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน
ค่าเริ่มต้น: คอมโพเนนต์ฝั่งเซิร์ฟเวอร์
ใน App Router คอมโพเนนต์ทั้งหมดเป็น คอมโพเนนต์ฝั่งเซิร์ฟเวอร์ โดยค่าเริ่มต้น คอมโพเนนต์เหล่านี้จะแสดงผลบนเซิร์ฟเวอร์ ไม่มี JavaScript ฝั่งไคลเอนต์เลย และสามารถเข้าถึงฐานข้อมูล ตัวแปรสภาพแวดล้อม และระบบไฟล์ได้โดยตรง
การเลือกใช้คอมโพเนนต์ฝั่งไคลเอนต์
เพิ่ม 'use client' ที่ด้านบนสุดของไฟล์เพื่อกำหนดให้เป็นคอมโพเนนต์ฝั่งไคลเอนต์ การนำเข้าทั้งหมดของคอมโพเนนต์นั้นจะกลายเป็นฝั่งไคลเอนต์ด้วย — นี่คือการสร้างขอบเขตฝั่งไคลเอนต์
'use client';
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}สิ่งที่คอมโพเนนต์ฝั่งเซิร์ฟเวอร์ทำได้
คอมโพเนนต์ฝั่งเซิร์ฟเวอร์สามารถ await การดึงข้อมูลภายในโค้ดได้ อ่านตัวแปรสภาพแวดล้อม เข้าถึงระบบไฟล์ และนำเข้าแพ็กเกจขนาดใหญ่ที่ใช้เฉพาะเซิร์ฟเวอร์ได้โดยไม่ทำให้ชุดโค้ดฝั่งไคลเอนต์มีขนาดเพิ่มขึ้น
// app/products/page.tsx — Server Component
export default async function ProductsPage() {
const products = await db.query('SELECT * FROM products');
return (
<ul>
{products.map(p => <li key={p.id}>{p.name}</li>)}
</ul>
);
}สิ่งที่คอมโพเนนต์ฝั่งเซิร์ฟเวอร์ทำไม่ได้
คอมโพเนนต์ฝั่งเซิร์ฟเวอร์ไม่สามารถใช้ฮุก (useState, useEffect) API ของเบราว์เซอร์ หรือตัวจัดการเหตุการณ์ได้ สิ่งเหล่านี้ต้องใช้ 'use client'
การประกอบคอมโพเนนต์ฝั่งเซิร์ฟเวอร์และฝั่งไคลเอนต์
ส่งผลลัพธ์ของคอมโพเนนต์ฝั่งเซิร์ฟเวอร์เป็นพร็อพหรือองค์ประกอบลูกให้คอมโพเนนต์ฝั่งไคลเอนต์ แนวทางหลักคือ เก็บการดึงข้อมูลไว้ในคอมโพเนนต์ฝั่งเซิร์ฟเวอร์ และเก็บการโต้ตอบไว้ในคอมโพเนนต์ฝั่งไคลเอนต์
// Server Component (no 'use client')
async function ProductPage({ id }) {
const product = await getProduct(id); // direct DB call
return <AddToCartButton product={product} />; // client component
}
// Client Component
'use client';
function AddToCartButton({ product }) {
const [added, setAdded] = useState(false);
return <button onClick={() => { addToCart(product); setAdded(true); }}>{added ? 'Added!' : 'Add to cart'}</button>;
}การส่งองค์ประกอบลูกจากเซิร์ฟเวอร์ไปยังไคลเอนต์
คอมโพเนนต์ฝั่งเซิร์ฟเวอร์สามารถส่ง JSX เป็น children ให้คอมโพเนนต์ฝั่งไคลเอนต์ได้ องค์ประกอบลูกจะยังคงแสดงผลบนเซิร์ฟเวอร์ ส่วนตัวครอบฝั่งไคลเอนต์จะเพิ่มการโต้ตอบให้
// Client wrapper — Modal with open/close state
'use client';
function Modal({ children }) {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)}>Open</button>
{open && <dialog>{children}</dialog>}
</>
);
}
// Server Component — passes server-fetched content into client modal
async function Page() {
const content = await fetchContent();
return <Modal><ServerRenderedContent data={content} /></Modal>;
}ขอบเขตฝั่งไคลเอนต์
การเพิ่ม 'use client' จะทำให้ไฟล์และการนำเข้าองค์ประกอบลูกทั้งหมดเป็นฝั่งไคลเอนต์ หากต้องการให้องค์ประกอบลูกยังเป็นคอมโพเนนต์ฝั่งเซิร์ฟเวอร์ ให้ส่งองค์ประกอบนั้นเป็นพร็อพหรือช่องแทนการนำเข้าโดยตรง
รูปแบบการดึงข้อมูล
ดึงข้อมูลในคอมโพเนนต์ฝั่งเซิร์ฟเวอร์แล้วส่งต่อข้อมูลลงไป หลีกเลี่ยงการดึงข้อมูลในคอมโพเนนต์ฝั่งไคลเอนต์เมื่อทำได้ — เพราะจะเพิ่มขนาดชุดโค้ดฝั่งไคลเอนต์และทำให้ตรรกะฝั่งเซิร์ฟเวอร์ซ้ำซ้อน
// Good: fetch in server, pass to client
async function Page() {
const user = await getUser();
return <UserProfile user={user} />; // client component
}
// Avoid: fetch in client
'use client';
function UserProfile() {
const { data } = useSWR('/api/user', fetcher); // network request from browser
}ยูทิลิตีที่ใช้เฉพาะเซิร์ฟเวอร์
แพ็กเกจ server-only จะแจ้งข้อผิดพลาดระหว่างการสร้าง หากมีการนำเข้าโมดูลที่ใช้เฉพาะเซิร์ฟเวอร์เข้าไปในคอมโพเนนต์ฝั่งไคลเอนต์โดยไม่ตั้งใจ
// lib/db.ts
import 'server-only'; // throws at build time if imported in 'use client' file
export const db = createDbClient(process.env.DB_URL);การแชร์สถานะระหว่างเซิร์ฟเวอร์และไคลเอนต์
คอมโพเนนต์ฝั่งเซิร์ฟเวอร์ไม่สามารถเก็บสถานะได้ หากต้องการแชร์สถานะจากการดึงข้อมูลบนเซิร์ฟเวอร์ไปยังคอมโพเนนต์ฝั่งไคลเอนต์ที่มีการโต้ตอบ ให้ส่งสถานะนั้นเป็นพร็อพในการแสดงผลครั้งแรก แล้วจัดการการอัปเดตบนไคลเอนต์
เมื่อใดควรเพิ่ม use client
เพิ่ม 'use client' เมื่อจำเป็นต้องใช้สิ่งต่อไปนี้: ฮุก (useState, useEffect), เหตุการณ์ของเบราว์เซอร์ (onClick), API ของเบราว์เซอร์ (localStorage, window) หรือไลบรารีฝั่งไคลเอนต์จากบุคคลที่สาม
ตรวจสอบอย่างรวดเร็ว
คุณต้องเพิ่มสิ่งใดที่ด้านบนสุดของไฟล์เพื่อใช้ useState หรือ onClick ใน App Router ของ Next.js
สรุป
คอมโพเนนต์ทั้งหมดของ App Router เป็นคอมโพเนนต์ฝั่งเซิร์ฟเวอร์โดยค่าเริ่มต้น — ไม่มีชุดโค้ด JS และเข้าถึงข้อมูลได้โดยตรง เพิ่ม 'use client' เฉพาะจุดที่ต้องการการโต้ตอบ ประกอบคอมโพเนนต์โดยส่งข้อมูลที่ดึงจากเซิร์ฟเวอร์เป็นพร็อพหรือองค์ประกอบลูกให้ตัวครอบฝั่งไคลเอนต์ และรักษาขอบเขตฝั่งไคลเอนต์ให้ใกล้กับใบไม้ของต้นไม้คอมโพเนนต์มากที่สุด
คำถามที่พบบ่อย
บทเรียน “คอมโพเนนต์ฝั่งเซิร์ฟเวอร์กับฝั่งไคลเอ็นต์ใน Next.js” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “คอมโพเนนต์ฝั่งเซิร์ฟเวอร์กับฝั่งไคลเอ็นต์ใน Next.js” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “คอมโพเนนต์ฝั่งเซิร์ฟเวอร์กับฝั่งไคลเอ็นต์ใน Next.js”
ตัดสินใจว่าจะเพิ่ม 'use client' เมื่อใด และประกอบโครงสร้างฝั่งเซิร์ฟเวอร์กับฝั่งไคลเอ็นต์อย่างไร คุณปฏิบัติ React Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “คอมโพเนนต์ฝั่งเซิร์ฟเวอร์กับฝั่งไคลเอ็นต์ใน Next.js” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน React Academy นี้ได้ไหม
ได้ บทเรียน React Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- รูปแบบการตั้งชื่อไฟล์ของ App Router
- คอมโพเนนต์ฝั่งเซิร์ฟเวอร์กับฝั่งไคลเอ็นต์ใน Next.js
- เส้นทางแบบไดนามิกและกลุ่มเส้นทาง
- Metadata API และ SEO ใน App Router