หลบหนีจากกับดัก: วิธีแก้ไข Stale Closures ใน React Hooks
Stale closures เป็นสาเหตุที่ทำให้เกิดการสูญเสียข้อมูลโดยไม่รู้ตัวใน React
คุณกำลังสร้างแดชบอร์ดที่มีตัวจับเวลาทำงานอยู่เบื้องหลัง โดยใช้ setInterval ภายใน useEffect hook เพื่อบันทึกข้อมูลอัตโนมัติทุกๆ 5 วินาที
บั๊กจะเกิดขึ้นเมื่ออินเทอร์วัลทำงาน โดยมันจะบันทึกเอกสารที่ว่างเปล่า ทั้งที่ผู้ใช้อาจจะพิมพ์ไปเต็มหน้าแล้วก็ตาม อินเทอร์วัลยังคงติดอยู่ในอดีตและเรียกใช้ state เวอร์ชันเก่าของคุณ
ปัญหาที่เกิดขึ้น
เมื่อ useEffect ทำงาน มันจะทำการจับค่า (capture) ตัวแปรต่างๆ ที่อยู่ใน scope ของมันไว้
- หากคุณไม่ใส่ state ลงใน dependency array ตัวอินเทอร์วัลจะใช้ค่า state จากการเรนเดอร์ครั้งแรก
- หากคุณใส่ state ลงใน dependency array ตัว React จะเริ่มอินเทอร์วัลใหม่ทุกครั้งที่มีการพิมพ์ (keystroke) ซึ่งจะส่งผลเสียต่อประสิทธิภาพและทำให้จังหวะเวลา (timing) ของคุณผิดเพี้ยนไป
วิธีแก้ไข: รูปแบบ Mutable Ref
คุณต้องแยกตัวจับเวลาออกจากข้อมูล โดยใช้ useRef hook เพื่อเก็บการอ้างอิง (reference) ที่คงที่ไปยัง state ล่าสุดของคุณ วิธีนี้จะช่วยหลีกเลี่ยงการ re-render และทำให้อินเทอร์วัลของคุณทำงานได้อย่างเสถียร
วิธีการนำไปใช้งาน:
- สร้าง ref เพื่อเก็บค่า state ล่าสุดของคุณ
- ใช้
useEffectเพื่ออัปเดต ref นั้นทุกครั้งที่ state เปลี่ยนแปลง - เริ่มต้นอินเทอร์วัลด้วย dependency array ว่างเปล่า เพื่อให้มันทำงานเพียงครั้งเดียว
- เข้าถึง ref ภายใน callback ของอินเทอร์วัล
วิธีนี้จะช่วยให้มั่นใจได้ว่างานที่ทำงานอยู่เบื้องหลังจะใช้ข้อมูลที่สดใหม่อยู่เสมอ ช่วยให้ UI ของคุณทำงานได้รวดเร็วและข้อมูลของคุณปลอดภัย
ที่มา: https://dev.to/iprajapatiparesh/escaping-the-trap-fixing-stale-closures-in-react-hooks-4gg7