ถ้าคุณเป็นสาย React น่าจะคุ้นเคยกับการใช้ useState และ useEffect กันอยู่แล้ว แต่เคยสงสัยไหมว่า เวลาเราทำ Client-side Rendering (CSR) ควรใช้สองตัวนี้ยังไงให้ถูกต้อง?
ในบทความนี้ เราจะมาดูวิธีใช้ useState และ useEffect ในการจัดการข้อมูลแบบ CSR (Client-side Rendering) พร้อมตัวอย่างโค้ดจริง และข้อควรระวังที่ต้องระวัง ถ้าพร้อมแล้ว ไปดูกันเลย! 🚀
🎯 Client-side Rendering (CSR) คืออะไร?
ก่อนจะไปดู useState และ useEffect มาทำความเข้าใจ CSR (Client-side Rendering) กันก่อน
📌 CSR คือการเรนเดอร์หน้าเว็บบนฝั่งไคลเอนต์ (Client-side) โดยใช้ JavaScript ซึ่งหมายความว่า ทุกอย่างถูกโหลดผ่านเบราว์เซอร์ แทนที่จะให้เซิร์ฟเวอร์ส่งหน้า HTML มาให้แบบสมบูรณ์
🔍 ลักษณะของ CSR:
- เมื่อเข้าเว็บครั้งแรก เบราว์เซอร์จะโหลดไฟล์ HTML + JavaScript
- JavaScript จะรันบนฝั่งไคลเอนต์ เพื่อสร้าง UI และดึงข้อมูลจาก API
- เหมาะกับแอปที่ต้องการ อินเตอร์แอคทีฟสูง เช่น Dashboard หรือ Web App
- แต่ SEO อาจไม่ดี เพราะหน้าเว็บไม่มีข้อมูล HTML ให้บอทอ่าน (ต้องใช้ Next.js + SSR/SSG แก้ปัญหา)
🛠 การใช้ useState และ useEffect สำหรับ CSR
📌 useState คืออะไร?
useState เป็น React Hook ที่ใช้จัดการ state (ข้อมูลที่เปลี่ยนแปลงได้) ในคอมโพเนนต์ ฟังก์ชันนี้ช่วยให้เราสร้างตัวแปร state และอัปเดตค่าได้ง่าย ๆ
📌 useEffect คืออะไร?
useEffect เป็น React Hook ที่ใช้จัดการ side effects เช่น
- เรียก API
- เปลี่ยนชื่อเอกสาร (document.title)
- ตั้งค่า setTimeout หรือ setInterval
🏗 ตัวอย่างการใช้ useState และ useEffect ใน CSR
มาดูกันว่า เราสามารถใช้ useState และ useEffect ใน CSR ได้ยังไง โดยสมมติว่าเราต้องการ ดึงข้อมูลผู้ใช้จาก API และแสดงผลในเว็บ
1. โหลดข้อมูลจาก API ด้วย useEffect
import React, { useState, useEffect } from 'react';
const UsersList = () => {
const [users, setUsers] = useState([]); // ใช้ useState เก็บข้อมูลผู้ใช้
const [loading, setLoading] = useState(true); // ใช้ state เช็กว่ากำลังโหลดข้อมูลอยู่ไหม
useEffect(() => {
// ดึงข้อมูลจาก API เมื่อคอมโพเนนต์โหลดครั้งแรก
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((data) => {
setUsers(data); // อัปเดต state
setLoading(false); // ปิดสถานะ loading
});
}, []); // ใส่ [] หมายความว่าจะรันแค่ครั้งเดียวตอนโหลดหน้า
return (
<div>
<h1>รายชื่อผู้ใช้</h1>
{loading ? <p>กำลังโหลดข้อมูล...</p> : null}
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};
export default UsersList;
🔍 อธิบายโค้ด
- ใช้ useState([]) เพื่อเก็บข้อมูลผู้ใช้
- ใช้ useEffect เพื่อเรียก API ตอนคอมโพเนนต์โหลดครั้งแรก
- ใช้ setUsers(data) เพื่ออัปเดตข้อมูล
- ใช้ setLoading(false) เพื่อปิดสถานะโหลด
2. ใช้ useEffect จัดการ Event Listener
สมมติว่าเราต้องการให้หน้าเว็บ เช็กขนาดหน้าจอ (window size) และอัปเดตทุกครั้งที่เปลี่ยนขนาด
import React, { useState, useEffect } from 'react';
const WindowSize = () => {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize); // ลบ Event Listener ตอนคอมโพเนนต์ unmount
};
}, []);
return (
<div>
<h1>ขนาดหน้าจอ: {width}px</h1>
</div>
);
};
export default WindowSize;
🔍 อธิบายโค้ด
- ใช้ useState เพื่อเก็บค่าความกว้างของหน้าจอ
- ใช้ useEffect เพิ่ม event listener resize ตอนโหลด
- ใช้ return () => {} เพื่อลบ event listener ตอนคอมโพเนนต์ถูกถอดออก
🔥 ข้อควรระวังในการใช้ useEffect และ useState
⚠️ 1. อย่าดึง API ใน useEffect แบบไม่มี Dependency Array
ถ้าคุณลืมใส่ [] มันจะรันซ้ำ ทุกครั้งที่คอมโพเนนต์ re-render ทำให้ API ถูกเรียกหลายรอบเกินไป
❌ โค้ดผิด:
useEffect(() => {
fetchData(); // จะเรียก API ทุกครั้งที่ state เปลี่ยน
});
✅ โค้ดที่ถูกต้อง:
useEffect(() => {
fetchData(); // เรียก API แค่ครั้งเดียว
}, []);
⚠️ 2. อย่าอัปเดต state ใน useEffect โดยไม่มีเงื่อนไข
ถ้าเราอัปเดต state โดยไม่มีเงื่อนไข มันจะทำให้เกิด Infinite Loop ได้
❌ โค้ดผิด:
useEffect(() => {
setCount(count + 1); // ทำให้เกิดลูป เพราะการอัปเดต state ทำให้ useEffect รันใหม่
}, [count]);
✅ โค้ดที่ถูกต้อง:
useEffect(() => {
if (count < 10) setCount(count + 1);
}, [count]); // ตรวจสอบก่อนอัปเดต state
📌 สรุป
- useState ใช้เก็บข้อมูลที่เปลี่ยนแปลงได้ในคอมโพเนนต์
- useEffect ใช้ดึงข้อมูลจาก API, จัดการ Event Listener, และทำงานที่ต้องเกิดหลังจาก render
- CSR เหมาะกับเว็บที่ต้องการโต้ตอบเยอะ แต่ไม่เหมาะกับ SEO
- ควรระวังการใช้ useEffect ไม่ให้เกิด Infinite Loop หรือ API ถูกเรียกซ้ำ
ถ้าคุณเข้าใจการใช้ useState และ useEffect แล้ว คุณสามารถพัฒนาเว็บแบบ CSR ได้อย่างมีประสิทธิภาพ 🚀