React Hook คือฟังก์ชันพิเศษที่ให้ function component ใน React มีความสามารถที่แต่ก่อนทำได้เฉพาะใน class component เท่านั้น เช่น การเก็บ state (ข้อมูลที่เปลี่ยนแปลงได้) หรือการทำงานที่มีผลข้างเคียง (side effect) อย่างการดึงข้อมูลจาก API บทความนี้จะอธิบาย React Hook คืออะไร พร้อมตัวอย่าง useState และ useEffect ซึ่งเป็นสอง Hook ที่ใช้บ่อยที่สุด
ถ้ากำลังเรียน React อยู่ ไม่ว่าจะตามคอร์สไหนหรืออ่านเอกสารทางการ จะเจอคำว่า Hook แทบทุกหน้า เพราะเป็นแกนหลักของการเขียน React สมัยใหม่ทั้งหมด เข้าใจ Hook ให้แน่นตั้งแต่ต้นจะทำให้เรียนรู้ concept อื่นของ React ต่อไปได้ง่ายขึ้นมาก
ทำไมถึงมี React Hook
ก่อนที่ React จะเปิดตัว Hook ในเวอร์ชัน 16.8 (ปี 2019) การเขียน component ที่ต้องการ state ต้องเขียนเป็น class component ซึ่งมีโครงสร้างซับซ้อนกว่า ต้องเข้าใจเรื่อง this, constructor และ lifecycle method ต่างๆ ทำให้เขียนยากและอ่านยากกว่าที่ควรจะเป็น โดยเฉพาะสำหรับมือใหม่
Hook เข้ามาแก้ปัญหานี้โดยให้ function component (ที่เขียนง่ายกว่ามาก) มีความสามารถเทียบเท่า class component ได้ ปัจจุบันโปรเจกต์ React ใหม่แทบทั้งหมดเขียนด้วย function component ร่วมกับ Hook เป็นมาตรฐาน ไม่นิยมเขียน class component แบบเดิมอีกแล้ว เอกสารทางการของ React เองก็แนะนำให้เริ่มเรียนรู้ผ่าน function component และ Hook ตั้งแต่แรกด้วยเช่นกัน
useState คืออะไร ใช้ยังไง
useState คือ Hook ที่ใช้เก็บและอัปเดต state — ค่าที่เปลี่ยนแปลงได้และทำให้ component render ใหม่เมื่อค่าเปลี่ยน
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>กดไปแล้ว {count} ครั้ง</p>
<button onClick={() => setCount(count + 1)}>กด</button>
</div>
);
}
useState(0) สร้างตัวแปร state ชื่อ count เริ่มต้นที่ 0 พร้อมฟังก์ชัน setCount สำหรับอัปเดตค่า ทุกครั้งที่กดปุ่ม setCount(count + 1) จะถูกเรียก React จะอัปเดตค่า count แล้ว render component ใหม่ให้แสดงตัวเลขล่าสุดทันที
จุดสำคัญคือ ห้ามแก้ state โดยตรง เช่นพิมพ์ count = count + 1 ตรงๆ เพราะ React จะไม่รู้ว่าค่าเปลี่ยนและจะไม่ render ใหม่ให้ ต้องเรียกผ่านฟังก์ชัน setCount ที่ useState ให้มาเท่านั้น
useEffect คืออะไร ใช้ยังไง
useEffect คือ Hook ที่ใช้รันโค้ดที่มี side effect — การทำงานที่ส่งผลกระทบนอกเหนือจากแค่แสดงผล UI เช่น ดึงข้อมูลจาก API, ตั้ง timer หรือแก้ไข DOM โดยตรง
import { useState, useEffect } from 'react';
function UserProfile() {
const [user, setUser] = useState(null);
useEffect(() => {
fetch('/api/user')
.then((res) => res.json())
.then((data) => setUser(data));
}, []);
return <div>{user ? user.name : 'กำลังโหลด...'}</div>;
}
useEffect รับฟังก์ชันเป็นพารามิเตอร์ตัวแรก ฟังก์ชันนั้นจะรันหลัง component render เสร็จ พารามิเตอร์ตัวที่สอง (array ว่างเปล่า [] ในตัวอย่างนี้) เรียกว่า dependency array บอก React ว่าให้รัน effect นี้เมื่อไหร่
[](array ว่าง) — รันแค่ครั้งเดียวตอน component ปรากฏครั้งแรกเท่านั้น[someValue]— รันใหม่ทุกครั้งที่someValueเปลี่ยนค่า- ไม่ใส่พารามิเตอร์ตัวที่สองเลย — รันทุกครั้งที่ component render ใหม่ (ควรหลีกเลี่ยงถ้าไม่จำเป็นจริงๆ เพราะอาจทำให้ทำงานถี่เกินไป)
cleanup function ใน useEffect ใช้ทำอะไร
บาง side effect ต้อง “เก็บกวาด” ตัวเองก่อนที่ component จะหายไป หรือก่อนที่ effect จะรันรอบใหม่ เช่น ยกเลิก timer หรือปิดการเชื่อมต่อ useEffect รองรับเรื่องนี้ผ่านการ return ฟังก์ชันออกมาจากภายใน effect
useEffect(() => {
const timer = setInterval(() => {
console.log('ทำงานทุกวินาที');
}, 1000);
return () => clearInterval(timer);
}, []);
ฟังก์ชันที่ return ออกมา (เรียกว่า cleanup function) จะถูกเรียกอัตโนมัติก่อนที่ component จะถูกถอดออกจากหน้าจอ หรือก่อน effect รอบถัดไปจะรันใหม่ ในตัวอย่างนี้ clearInterval ช่วยหยุด timer ไม่ให้ทำงานต่อไปเรื่อยๆ แม้ component จะถูกปิดไปแล้ว ถ้าลืมเขียน cleanup function อาจทำให้เกิด memory leak หรือพฤติกรรมแปลกๆ ที่ debug ยาก โดยเฉพาะกับ subscription หรือ event listener ที่เปิดค้างไว้ เป็นจุดที่มือใหม่มักมองข้ามเพราะโค้ดยังทำงานได้ปกติในระยะสั้น แต่จะเริ่มมีปัญหาเมื่อแอปใหญ่ขึ้นและมี component เปิดปิดบ่อยขึ้น
กฎของ Hook ที่ต้องรู้ (Rules of Hooks)
React มีกฎการใช้ Hook 2 ข้อที่ต้องทำตามเสมอ ไม่งั้นจะเจอ error หรือพฤติกรรมแปลกๆ
1. เรียก Hook ที่ top level ของ component เท่านั้น — ห้ามเรียก Hook ภายใน if, loop หรือฟังก์ชันซ้อนใน component เพราะ React ใช้ลำดับการเรียก Hook ในการจดจำว่า state ตัวไหนเป็นของอะไร ถ้าเรียกแบบมีเงื่อนไข ลำดับอาจเปลี่ยนไปมาระหว่างรอบ render ทำให้ React สับสน
2. เรียก Hook จาก React function component หรือ custom Hook เท่านั้น — ห้ามเรียก Hook จากฟังก์ชัน JavaScript ทั่วไปที่ไม่ใช่ component
ถ้าฝ่าฝืนกฎเหล่านี้ React (ผ่าน plugin ESLint ที่มากับ Create React App หรือ Vite) มักเตือนเป็น error หรือ warning ให้เห็นทันทีตั้งแต่ตอนเขียนโค้ด ไม่ต้องรอให้พังตอนรันจริงถึงจะรู้ตัว
Hook อื่นที่ควรรู้จักไว้
useContext — ดึงค่าจาก Context มาใช้ในบาง component โดยไม่ต้องส่งผ่าน props ทีละชั้น เหมาะกับข้อมูลที่ต้องใช้ร่วมกันหลาย component เช่น ธีมสีหรือข้อมูลผู้ใช้ที่ล็อกอินอยู่
useRef — เก็บค่าที่ไม่ต้องการให้ทำให้ component render ใหม่เมื่อเปลี่ยน หรือใช้อ้างอิงถึง DOM element โดยตรง
useMemo — เก็บผลลัพธ์ของการคำนวณที่หนักไว้ ไม่ต้องคำนวณใหม่ทุกครั้งที่ render ถ้าค่าที่ใช้คำนวณไม่ได้เปลี่ยนไป
Hook เหล่านี้ใช้บ่อยน้อยกว่า useState และ useEffect แนะนำให้เข้าใจสองตัวหลักให้แน่นก่อน แล้วค่อยเรียนรู้ตัวอื่นเพิ่มเมื่อเจอสถานการณ์ที่ต้องใช้จริง การพยายามจำทุก Hook พร้อมกันตั้งแต่แรกมักทำให้สับสนมากกว่าเข้าใจ
useState กับ useReducer ต่างกันยังไง
เมื่อ state เริ่มซับซ้อนขึ้น เช่น มีหลายค่าที่เปลี่ยนพร้อมกันตามเงื่อนไขต่างๆ useState เพียงอย่างเดียวอาจทำให้โค้ดยุ่งเหยิง React มี Hook อีกตัวชื่อ useReducer ที่เหมาะกับสถานการณ์นี้มากกว่า
useState เหมาะกับ state ที่เรียบง่าย เปลี่ยนค่าตรงไปตรงมา เช่น ตัวเลข, ข้อความ หรือ boolean เดี่ยวๆ ส่วน useReducer เหมาะกับ state ที่มีโครงสร้างซับซ้อน หรือการเปลี่ยนค่าขึ้นอยู่กับ “action” หลายแบบ (คล้ายรูปแบบที่ Redux ใช้) ทำให้ logic การอัปเดต state ทั้งหมดรวมอยู่ในที่เดียวแทนที่จะกระจายอยู่หลายจุดในโค้ด
สำหรับมือใหม่ ไม่จำเป็นต้องรีบเรียนรู้ useReducer ทันที ใช้ useState ให้คล่องก่อน แล้วค่อยเปลี่ยนไปใช้ useReducer เมื่อรู้สึกว่า useState เริ่มจัดการ state ที่ซับซ้อนได้ไม่สะดวกแล้วก็ยังไม่สาย ทั้งสอง Hook แก้ปัญหาเดียวกันแค่คนละวิธี เลือกใช้ตามความเหมาะสมของแต่ละสถานการณ์ได้เลย
Custom Hook คืออะไร
นอกจาก Hook ที่ React มีให้ ยังสร้าง custom Hook ของตัวเองได้ เพื่อรวม logic ที่ใช้ซ้ำหลาย component เข้าไว้ในที่เดียว ตามธรรมเนียมชื่อ custom Hook ต้องขึ้นต้นด้วยคำว่า use เสมอ เช่น useWindowSize, useFetch เพื่อให้ React และเครื่องมือ dev tools รู้จักว่าเป็น Hook custom Hook ช่วยลดการเขียนโค้ดซ้ำๆ ระหว่างหลาย component ได้มาก โดยเฉพาะ logic ที่ใช้ useState กับ useEffect ร่วมกันในรูปแบบเดิมซ้ำๆ
คำถามที่พบบ่อย
ต้องรู้ Hook ทุกตัวก่อนถึงจะเขียน React ได้ไหม ไม่จำเป็น เริ่มจาก useState และ useEffect ให้คล่องก่อนก็เพียงพอสำหรับงานทั่วไปแล้ว ค่อยเรียนรู้ Hook อื่นเพิ่มเมื่อเจอสถานการณ์ที่ต้องใช้จริง ไม่ต้องพยายามจำทุกอย่างตั้งแต่วันแรก
class component ยังใช้ได้อยู่ไหม ยังใช้ได้ React ไม่ได้ตัด class component ออก แต่ไม่แนะนำให้เขียนใหม่ด้วย class component อีกแล้ว โปรเจกต์ใหม่ควรใช้ function component กับ Hook เป็นมาตรฐาน โค้ดเก่าที่เป็น class component ยังทำงานร่วมกับโค้ดใหม่ที่เป็น function component ได้ปกติ
useEffect รันกี่ครั้งกันแน่ ขึ้นอยู่กับ dependency array ที่ใส่ไว้ ถ้าเป็น array ว่างรันครั้งเดียว ถ้าใส่ตัวแปรไว้จะรันใหม่ทุกครั้งที่ตัวแปรนั้นเปลี่ยนค่า ข้อควรระวังคือ React เวอร์ชันใหม่ใน Strict Mode (โหมดพัฒนา) จะรัน effect สองครั้งตอน development เพื่อช่วยจับบั๊ก ไม่ใช่บั๊กของโค้ดคุณเอง เป็นพฤติกรรมที่ตั้งใจของ React เอง
Hook ใช้ได้กับ TypeScript ไหม ใช้ได้ปกติ Hook ทำงานร่วมกับ TypeScript ได้ดีมาก โดยเฉพาะ useState ที่ระบุ type ของ state ได้ชัดเจน เช่น useState<number>(0) ช่วยจับข้อผิดพลาดตั้งแต่ตอนเขียนโค้ดก่อนรันจริง
ทำไม useEffect รันซ้ำไม่หยุด (infinite loop) มักเกิดจากลืมใส่ dependency array หรือใส่ค่าที่เปลี่ยนทุกครั้งที่ render เข้าไปใน dependency array เช่น object หรือ array ที่สร้างใหม่ทุกรอบ ทำให้ React มองว่าค่าเปลี่ยนตลอดเวลาแล้วรัน effect ซ้ำไม่หยุด วิธีแก้คือเช็คให้แน่ใจว่าใส่ dependency array ให้ถูกต้อง และหลีกเลี่ยงการสร้าง object/array ใหม่ทุกรอบถ้าไม่จำเป็น
เรียก Hook ตามเงื่อนไขได้ไหม เช่น เรียกเฉพาะบางกรณี ไม่ได้ ผิดกฎข้อแรกของ Hook โดยตรง ถ้าต้องการ logic แบบมีเงื่อนไข ให้เรียก Hook ไว้ที่ top level เสมอ แล้วค่อยใส่เงื่อนไขภายในฟังก์ชันที่ Hook นั้นเรียกใช้แทน เช่น เรียก useEffect ไว้ปกติ แต่ใส่ if ไว้ข้างในฟังก์ชันที่ effect รัน ไม่ใช่ครอบ useEffect ทั้งก้อนด้วย if หลักการนี้ใช้ได้กับ Hook ทุกตัว ไม่ใช่แค่ useEffect เท่านั้น
สรุป
React Hook คือฟังก์ชันที่ให้ function component มี state และ side effect ได้ โดยไม่ต้องเขียนเป็น class component ที่ซับซ้อนกว่า
จุดสำคัญที่ต้องจำ
useStateใช้เก็บและอัปเดต state ที่ทำให้ component render ใหม่เมื่อค่าเปลี่ยนuseEffectใช้รันโค้ดที่มี side effect เช่น ดึงข้อมูลจาก API ควบคุมด้วย dependency array- เรียก Hook ที่ top level ของ component เท่านั้น ห้ามเรียกใน condition หรือ loop
เริ่มฝึกจาก useState และ useEffect ให้คล่องก่อน จะทำให้เข้าใจ Hook อื่นได้ง่ายขึ้นมากเมื่อต้องเรียนรู้เพิ่มในอนาคต ลองเขียนโปรเจกต์เล็กๆ ด้วยตัวเองจะช่วยให้จำได้แม่นกว่าอ่านเฉยๆ มาก
1 thought on “React Hook คืออะไร ใช้ทำอะไรบ้าง (useState, useEffect เบื้องต้น)”