หน้าหลัก/บทเรียนขั้นสูง/6. React Hooks พื้นฐาน
เวลาเรียนโดยประมาณ: 25 นาที
Chapter 6: React State & Lifecycle

React Hooks พื้นฐาน ปลูกฝังสมองและความจำให้ UI!

เคยสงสัยไหมว่าหน้าเว็บที่ดูนิ่งๆ สามารถ "จำ" สิ่งที่เราพิมพ์, ปุ่มที่เรากดเปิดปิด, หรือยิงดึงข้อมูลจาก Server ขึ้นมาแสดงผลตอนหน้าจอเริ่มเปิดได้อย่างไร? ยินดีต้อนรับเข้าสู่โลกของ React Hooks พลังพิเศษที่เปลี่ยนฟังก์ชันธรรมดาให้กลายเป็น Component อัจฉริยะ!

React Hooks Illustration

พจนานุกรมปูพื้นฐานสมอง React Hooks (Hooks Dictionary)

ปูพื้นฐานคำศัพท์หัวใจสำคัญในการจัดการสเตตัสความทรงจำและการเฝ้าระวังสิ่งแวดล้อม:

1. React Hooks (เบ็ดเชื่อมพลัง)

กลุ่มฟังก์ชันพิเศษที่ขึ้นต้นด้วย use (เช่น useState, useEffect) ที่ทำหน้าที่คล้ายเบ็ดโยนไปเกี่ยวพลังจำและวงจรของ React Engine มาให้ฟังก์ชันปกติใช้งาน

2. State (สเตตัสความจำ)

ตัวแปรพิเศษที่ทำหน้าที่เปรียบเหมือนสมุดบันทึกใน React Engine ซึ่งหากค่าของข้อมูลนี้มีการเปลี่ยนแปลง จะสั่งสั่งให้หน้าเว็บวาดตัวเองอัปเดตใหม่ทันที

3. Side Effect (ผลกระทบประกอบร่วม)

การทำงานส่วนเสริมที่นอกเหนือจากการวาดปุ่มและดีไซน์หลัก เช่น การเชื่อมต่อดึงข้อมูล API ภายนอก หรือการแอบสั่งพิมพ์ข้อความลง Log หลังบ้าน

4. Dependency Array (กล่องตรวจวัดเปลี่ยน)

รายการตัวแปรที่ใส่ท้ายคำสั่ง useEffect เพื่อกำหนดขอบเขตควบคุมว่าหากตัวแปรเหล่านั้นเปลี่ยนแปลงเท่านั้น จึงจะสั่งรันโค้ดประมวลผล Side Effect ซ้ำอีกรอบ

1ทำไมฟังก์ชันธรรมดาถึงต้องมี Hooks? 🤔

ในยุคก่อนหน้านี้ การทำให้ Component จดจำข้อมูลบางอย่างได้ เราต้องเขียนโค้ดด้วยรูปแบบ Class Component ที่เข้าใจยากและยุ่งเหยิงมาก แต่ใน React ยุคใหม่ เราเขียน Component ด้วย JavaScript Function ธรรมดาๆ แทน เพื่อความคล่องตัวและกระชับของโค้ด

ทว่า... ในโลกของโปรแกรมมิ่ง JavaScript ฟังก์ชันทั่วไปมีคุณสมบัติหนึ่งที่เป็นอุปสรรคต่อการทำ UI นั่นคือ **"ความจำเสื่อมชั่วคราว (Statelessness)"** เมื่อฟังก์ชันทำงานบรรทัดสุดท้ายเสร็จและ return หน้าจอ HTML ออกมาแล้ว **ตัวแปรภายในทั้งหมดจะสลายหายไปจากหน่วยความจำทันที!** และเมื่อมีการเรนเดอร์ใหม่ มันก็จะเริ่มต้นนับหนึ่งใหม่เสมอ

เปรียบเทียบให้เห็นภาพ: ปลาทอง กับ สมุดโน้ตกันน้ำ 📝🐠

🐠 1. ฟังก์ชันธรรมดา (ดั่งปลาทอง)

ทุกๆ ครั้งที่เกิดการวาดหน้าจอใหม่ (Re-render) ฟังก์ชันจะถูกสั่งให้รันตั้งแต่บรรทัดแรกใหม่หมด เปรียบเหมือนปลาทองที่ว่ายน้ำวนกลับมาที่เดิมแล้ว **ลืมทุกอย่างที่เกิดขึ้นก่อนหน้า** ไม่เหลือความจำเดิมอยู่เลย

📒 2. ฟังก์ชันที่มี Hooks (สมุดโน้ตกันน้ำ)

Hooks จะทำหน้าที่เหมือน **"เบ็ด"** ที่โยนออกไปนอกตัวปลาทอง เพื่อไป **"เกี่ยว" เอาสมุดโน้ตที่อยู่นอกตัวฟังก์ชัน (ใน React Engine)** กลับมาอ่าน ทำให้รู้ว่าก่อนหน้านี้เคยจดอะไรไว้ และอัปเดตข้อมูลนั้นได้อย่างต่อเนื่อง

ทำไมตัวแปรปกติถึง "อัปเดตหน้าจอเว็บไม่ได้"?

ลองจินตนาการว่าคุณสร้างตัวแปรธรรมดา let count = 0; ไว้ในฟังก์ชัน แล้วกดเพิ่มค่าผ่าน count++:

  • ค่าในหน่วยความจำ RAM เปลี่ยนแปลงจริง: ตัวแปรกลายเป็น 1, 2, 3... จริงๆ
  • แต่หน้าจอไม่เปลี่ยน: เพราะ React ไม่รู้เรื่องเลย! ไม่มีกลไกใดส่งสัญญาณบอก React Engine ว่า "เฮ้! ค่าเปลี่ยนแล้วนะ ช่วยวาดรูป (Re-render) หน้าจอใหม่ให้ผู้ใช้เห็นหน่อย"
  • เมื่อถูกรีเรนเดอร์จากสาเหตุอื่น: ตัวแปร let count = 0; จะโดนประกาศทับและรีเซ็ตค่ากลับไปเป็น 0 ทันทีเหมือนไม่เคยมีอะไรเกิดขึ้น!

📊 ตารางเปรียบเทียบ: ตัวแปรปกติ vs ตัวแปรสถานะของ React (State)

คุณสมบัติตัวแปรปกติ (let / const)ตัวแปรสถานะ React (State)
การเก็บรักษาค่า (Persistence)สลายหายไปทันทีเมื่อรันฟังก์ชันเสร็จ หรือโดนล้างเมื่อมี Re-renderReact ช่วยจำไว้ในสมองส่วนกลางอย่างปลอดภัย ไม่หายไปไหน
การสั่งวาดหน้าจอใหม่ (Re-render)❌ ไม่ส่งผลใดๆ ต่อการแสดงผลหน้าเว็บ✅ สั่งให้ React วาดหน้าจออัปเดตใหม่ทันทีที่เปลี่ยนค่า
วิธีเรียกใช้งานlet count = 0;const [count, setCount] = useState(0);
วิธีอัปเดตค่าcount = count + 1;setCount(count + 1);

นี่จึงเป็นเหตุผลที่ React สร้าง **Hooks (เบ็ดเกี่ยว)** ขึ้นมา! มันคือกลุ่มฟังก์ชันพิเศษที่ขึ้นต้นด้วยคำว่า use(เช่น useState, useEffect) ซึ่งออกแบบมาเพื่อให้เราสามารถ **"โยนเบ็ดไปเกี่ยวเบื้องหลังการทำงานหลักของ React Engine"** เพื่อหยิบยืมพลังพิเศษ เช่น ระบบความทรงจำระยะยาว (State) และระบบความเคลื่อนไหว (Lifecycle) มาสวมใส่ให้กับฟังก์ชันธรรมดาของเราได้อย่างสมบูรณ์แบบและทรงพลัง! 🚀

2useState() — เบ็ดกล่องความจำของ UI

เบ็ดตัวแรกและเป็นตัวที่เราหยิบมาใช้บ่อยที่สุดก็คือ useState หน้าที่ของมันคือ "สร้างกล่องเก็บสถานะในสมองของ Component"

ไวยากรณ์ในการเขียนแสนเรียบง่าย แต่มีเอกลักษณ์ดังนี้:

ตัวอย่างการประกาศ useState
import { useState } from "react"; function Counter() { // 1. ประกาศตัวแปรจดจำสถานะชื่อ count และฟังก์ชันอัปเดตชื่อ setCount const [count, setCount] = useState(0); // เริ่มต้นด้วยเลข 0 return ( <div> <p>คุณกดคลิกไปแล้ว {count} ครั้ง</p> {/* 2. สั่งเปลี่ยนค่าผ่าน setCount เพื่อบอก React ให้วาดหน้าจอใหม่ */} <button onClick={() => setCount(count + 1)}> เพิ่มแต้ม </button> </div> ); }

💡 สังเกตการตั้งชื่อ: เรานิยมใช้โครงสร้าง [name, setName] เสมอ เช่น [isOn, setIsOn] หรือ [user, setUser] เพื่อความเข้าใจที่ชัดเจนตรงกันทั้งโลก

ทดลองเล่นกับสนามเด็กเล่นจำลอง (Interactive Playground)

ลองสลับไปที่แถบ 1. useState เพื่อควบคุมสวิตช์ไฟและพลังเตาปฏิกรณ์ด้านล่างนี้ แล้วดูการจำลองการเปลี่ยนค่าของ State และการวาดภาพ Render บนหน้าจอจริงได้เลย!

คอนโทรลรูม (Control Panel)

สวิตช์เปิด-ปิดไฟ (isOn)FALSE
กดเพื่อบันทึกสถานะลงในตัวแปร state ตัวที่ 1
ปรับความแรงของเตาปฏิกรณ์ (power)50%
0% (Min)50% (Default)100% (Max)
เลือกสียอดฮิต (colorTheme)
โค้ดที่รันอยู่เบื้องหลัง (Behind the Scenes)
const [power, setPower] = useState(50);
const [isOn, setIsOn] = useState(false);
const [theme, setTheme] = useState("cyan");
เตาปฏิกรณ์ Arc Reactor (Rendered UI)

เมื่อ State เปลี่ยนแปลง เตาปฏิกรณ์จะเรนเดอร์ภาพใหม่ทันที!

STATE 1: [isOn]Inactive (False)
STATE 2: [power]50% Power
useState เอาไว้จดจำข้อมูลชิ้นเล็กชิ้นน้อยใน Component เมื่ออัปเดต จะสั่งแอปให้วาดหน้าจอ (Render) ใหม่เสมอ

3useEffect() — ตากล้องที่คอยดักดูความเคลื่อนไหว

เมื่อ Component ของเรามีสมองเอาไว้จำสิ่งต่างๆ แล้ว (ด้วย useState) บางทีเราอาจจะอยากให้เกิด "ผลลัพธ์ข้างเคียง (Side Effects)" นอกเหนือจากการแสดงผล HTML ปกติ เช่น:

  • "เมื่อหลอดไฟเปิด ให้บันทึกประวัติเหตุการณ์เก็บไว้ในตาราง"
  • "เมื่อเริ่มเปิดหน้าเว็บครั้งแรกสุด ให้ไปดึงข้อมูลราคาน้ำมันจาก API"
  • "เมื่อค่าพลังงานเปลี่ยน ให้แก้ไขหัวข้อบนแท็บเว็บบนสุด (Document Title)"

งานเหล่านี้เราจะทำผ่านเบ็ดตัวที่สองคือ useEffect ซึ่งมีไวยากรณ์ในการเขียนดังนี้:

โครงสร้าง useEffect
useEffect(() => { // 📸 โค้ดส่วนที่จะให้ทำงาน (Side Effect) console.log("พลังงานอัปเดตเป็น: " + power); return () => { // 🧹 (ตัวเลือกพิเศษ) ล้างข้อมูลส่วนเกิน (Cleanup Function) }; }, [power]); // 👁️ อาร์เรย์เฝ้าระวังตัวแปร (Dependency Array)

4ความลับของ Dependency Array 👁️

หัวใจที่ทำให้หลายคนงุนงงกับ useEffect มากที่สุดคือกล่องเหลี่ยมๆ ข้างหลังที่เรียกว่า Dependency Array (ชุดพารามิเตอร์เฝ้าระวัง)ซึ่งมีรูปแบบการส่งค่าเข้าไปอยู่ 3 แบบหลักๆ และให้ผลลัพธ์ต่างกันราวฟ้ากับเหว:

[]

อาร์เรย์ว่างเปล่า

รันคำสั่ง เพียงครั้งเดียวเท่านั้น ตอนที่ Component ปรากฏตัวบนหน้าจอครั้งแรกสุด (Mounting) เหมาะมากสำหรับการยิง API โหลดข้อมูลครั้งแรก

[state]

ระบุตัวแปรที่เฝ้า

รันคำสั่งครั้งแรก และจะรันซ้ำ ทุกครั้งที่ตัวแปรที่อยู่ข้างในกล่องมีการเปลี่ยนค่า เช่น เฝ้าพลังงาน เมื่อพลังงานเปลี่ยนก็จะรันฟังก์ชันทันที

ไม่มี

ละเว้นอาร์เรย์

⚠️ อันตราย! โค้ดข้างในจะรัน ทุกๆ ครั้งที่มีการเรนเดอร์ภาพใหม่ (ไม่ว่าใครเปลี่ยนก็ตาม) อาจส่งผลให้เว็บค้างได้ถ้าไปสั่งแก้ State ด้านในวนซ้ำ (Infinity Loop)

💡 คำแนะนำ: ลองสลับไปเล่นที่สนามเด็กเล่นด้านบนในแถบ 2. useEffect ดูอีกครั้ง ลองเลือกติ๊กถูก/ติ๊กออกในกล่อง "เฝ้า [power]" หรือ "เฝ้า [isOn]" แล้วทดลองเปลี่ยนค่าด้านซ้ายดู จะช่วยให้มองเห็นความสัมพันธ์ของ Dependency Array ได้ชัดเจนยิ่งขึ้น!

5กฎเหล็กของการใช้ Hooks 📜

เพื่อรักษาความมั่นคงและความถูกต้องในความทรงจำของ React เขาจึงตั้งกฎเหล็กไว้ 2 ข้อที่ห้ามโปรแกรมเมอร์ละเมิดเด็ดขาด:

1
ประกาศที่ระดับบนสุด (Only Call Hooks at the Top Level)

ห้ามเรียกใช้ Hooks ข้างในลูป (for), ข้างในคำสั่งเงื่อนไข (if) หรือฟังก์ชันย่อยซ้อนทับ เพราะ React จดจำสถานะตามลำดับการเรียกใช้งาน (Order)

2
เรียกจาก React เท่านั้น (Only Call Hooks from React Functions)

ห้ามเรียกใช้ Hooks ในไฟล์ JavaScript ทั่วไป ต้องเรียกใช้จากฟังก์ชันที่เป็น React Component หรือ Custom Hook เท่านั้น


บททดสอบท้ายบทเรียน (Quiz)

มาท้าทายสมองลองวัดความเข้าใจวิชา React Hooks กันหน่อย!

🧠 ทบทวนความเข้าใจบทที่ 6 (Mini Quiz)

ข้อ 1 จาก 5

Q:ฟังก์ชัน useState() จะส่งข้อมูล (return) กลับมาในรูปแบบ Array 2 ชิ้น สมาชิกสองตัวนี้คืออะไรตามลำดับ?

💡

ลองศึกษาเฉลยเพื่อดูแนวคิดเพิ่มเติม...

ถูกต้อง เมื่อเขียน const [power, setPower] = useState(50) สมาชิกตัวแรก (power) คือตัวแปรอ่านค่า ส่วนตัวที่สอง (setPower) คือฟังก์ชันแก้ไขค่า

คุณเรียนจบบทที่ 6 แล้ว!

บทต่อไป: การจัดการข้อมูล Array (map & filter)

เมื่อเข้าใจวิธีจดจำค่าเดี่ยวๆ แล้ว บทถัดไปจะเรียนรู้วิธีจัดการชุดข้อมูล (Array) ค้นหา คัดกรอง และปั๊ม Component ออกมาแสดงผลสไตล์มือโปร!

เรียนบทต่อไป