วันที่ 5 ของการเรียนรู้ React: Batching และ Functional Updates
ผมเคยคิดว่าการเรียกใช้ state setter หลายครั้งจะทำให้เกิดการ render หลายครั้ง
แต่ผมคิดผิด
React ฉลาดกว่านั้น มันใช้กระบวนการที่เรียกว่า Automatic Batching
แทนที่จะ render หลังจากทุกๆ การอัปเดต React จะรวบรวมการอัปเดตเหล่านั้นเข้าด้วยกัน โดยจะเก็บรวบรวมการอัปเดตทั้งหมดแล้วทำการ render เพียงครั้งเดียว ซึ่งช่วยเพิ่มประสิทธิภาพ (performance)
นี่คือสิ่งที่ผมได้เรียนรู้ในวันนี้
กระบวนการ Batching
เมื่อคุณเรียกใช้ฟังก์ชัน state หลายครั้ง React จะมีลำดับขั้นตอนดังนี้:
- เกิดการอัปเดต state หลายครั้ง
- React ทำการ batch การอัปเดตเหล่านั้นเข้าด้วยกัน
- React ทำการ render เพียงครั้งเดียว
- React commit การเปลี่ยนแปลงไปยัง UI
ปัญหาของการอัปเดตแบบมาตรฐาน (Standard Updates)
ผมลองใช้โค้ดนี้:
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
ผมคาดหวังว่าค่า count จะเพิ่มจาก 0 เป็น 3 แต่ผลลัพธ์กลับกลายเป็น 0 เป็น 1
สิ่งนี้เกิดขึ้นเพราะ setCount(count + 1) ไม่ได้หมายความว่า "เพิ่มค่า count"
แต่มันหมายถึง "ตั้งค่า count ให้เป็นค่าที่ระบุนี้"
ถ้า count คือ 0 ทุกบรรทัดจะบอก React ให้ตั้งค่า count เป็น 1 ซึ่ง React จะทำการ batch สิ่งเหล่านี้และเห็นว่าคำสั่งสุดท้ายคือการตั้งค่า count เป็น 1
วิธีแก้ไข: Functional Updates
เพื่อแก้ไขปัญหานี้ คุณต้องใช้ functional update ซึ่งจะใช้ค่า state ล่าสุดที่มีอยู่ใน update queue
วิธีที่ถูกต้อง:
setCount((prev) => prev + 1);
เมื่อคุณใช้รูปแบบนี้ React จะให้ค่าล่าสุดแก่การอัปเดตแต่ละครั้ง:
- การอัปเดตครั้งแรก: 0 + 1 = 1
- การอัปเดตครั้งที่สอง: 1 + 1 = 2
- การอัปเดตครั้งที่สาม: 2 + 1 = 3
ตอนนี้ตัวนับจะเพิ่มขึ้นถึง 3 จริงๆ
ข้อผิดพลาดที่พบบ่อย
ผมเคยเขียนแบบนี้:
setCount((prev) => { prev + 1 });
ตัวนับกลายเป็น undefined
เพราะเมื่อคุณใช้ปีกกา {} ใน arrow function คุณต้องใช้ keyword return ด้วย
ให้ใช้แบบนี้แทน:
setCount((prev) => prev + 1);
สรุปประเด็นสำคัญ:
- React ทำการ batch การอัปเดต state หลายครั้งเพื่อเพิ่มความเร็ว
- การเรียกใช้
setStateไม่ได้ทำให้เกิดการ render ทันทีเสมอไป - การอัปเดตแบบมาตรฐานจะใช้ค่าจากรอบการ render ปัจจุบัน
- Functional updates จะใช้ค่า state ล่าสุดจาก update queue
- React ใช้ Update Queue ภายในเพื่อจัดการการเปลี่ยนแปลงเหล่านี้
