𝗛𝗼𝘄 𝗔𝗱𝘃𝗮𝗻𝗰𝗲𝗱 𝗥𝗲𝗮𝗰𝘁 𝗗𝗲𝘃𝗲𝗹𝗼𝗽𝗲𝗿𝘀 𝗦𝗵𝗼𝘂𝗹𝗱 𝗧𝗵𝗶𝗻𝗸 𝗔𝗯𝗼𝘂𝘁 𝗛𝗼𝗼𝗸𝘀
นักพัฒนาส่วนใหญ่เรียนรู้เรื่อง hooks โดยไม่เข้าใจว่า React ทำการ render อย่างไร ซึ่งทำให้เกิดความสับสน หากต้องการเชี่ยวชาญเรื่อง hooks คุณต้องเข้าใจหน้าที่หลัก 5 ประการ:
• การจดจำข้อมูล • การทำงานของ side effects • การแชร์ข้อมูล • การเพิ่มประสิทธิภาพการ rendering • การควบคุมการจัดลำดับงาน (scheduling)
การเปลี่ยนแปลงของ state จะกระตุ้นให้เกิดการ re-render ซึ่งทุกครั้งที่มีการ re-render ตัวแปร, object และ function จะถูกสร้างขึ้นใหม่ ข้อเท็จจริงง่ายๆ นี้เองที่อธิบายว่าทำไม useMemo และ useCallback ถึงมีความสำคัญ
Understanding the Hooks
State and Ordering React เก็บ state ไว้ใน linked list ที่เชื่อมต่อกับ component Fiber นี่คือเหตุผลที่คุณไม่สามารถเรียกใช้ hooks ภายในเงื่อนไข (conditions) หรือลูป (loops) ได้ เพราะ React อาศัยลำดับการเรียกใช้งานเพื่อค้นหา state ที่ถูกต้อง
The Batching Reality เมื่อคุณเรียกใช้ setState, React จะทำการวางแผนการอัปเดต (schedule an update) แต่จะยังไม่เปลี่ยนค่าในทันที นี่คือเหตุผลว่าทำไมการ log state ทันทีหลังจากตั้งค่าจึงแสดงค่าเก่าออกมา ควรใช้รูปแบบ functional update เสมอเพื่อหลีกเลี่ยงข้อมูลที่ล้าสมัย (stale data):
- แบบที่ไม่ควรทำ:
setCount(count + 1) - แบบที่ควรทำ:
setCount(prev => prev + 1)
The useEffect Mental Model เลิกปฏิบัติกับ useEffect เหมือนเป็น lifecycle method แต่ให้ใช้มันเพื่อซิงโครไนซ์ (synchronize) component ของคุณกับระบบภายนอก เช่น APIs หรือ WebSockets
ข้อสำคัญ: React จะวาดหน้าจอ (paint the screen) ก่อนที่ useEffect จะทำงาน เพื่อให้แน่ใจว่า effect ของคุณจะไม่ไปขัดขวางการแสดงผลของ UI หากคุณจำเป็นต้องวัดขนาด DOM ก่อนที่ผู้ใช้จะมองเห็น ให้ใช้ useLayoutEffect แทน
The useRef Reality
ref ไม่ได้มีไว้สำหรับ DOM elements เท่านั้น แต่มันคือ container ที่สามารถเปลี่ยนแปลงค่าได้ (mutable) และคงอยู่ตลอด (persistent) โดย React จะรักษา object reference เดิมไว้ระหว่างการ render การเปลี่ยนค่า ref.current จะไม่กระตุ้นให้เกิดการ re-render ให้ใช้มันสำหรับพวก timer, socket หรือการเก็บค่าก่อนหน้า (previous values)
The Memoization Trap useMemo ไม่ใช่ปุ่มวิเศษที่จะช่วยให้แอปเร็วขึ้นเสมอไป เพราะมันมีต้นทุน (overhead cost) ที่ต้องจ่าย เนื่องจาก React ต้องทำการจัดเก็บ cache และเปรียบเทียบ dependencies
ควรใช้ useMemo ก็ต่อเมื่อต้นทุนในการคำนวณนั้นสูงกว่าต้นทุนในการทำ memoization เท่านั้น หากคุณใช้มันกับการคำนวณทางคณิตศาสตร์ง่ายๆ คุณกำลังทำให้แอปของคุณช้าลง
Context is not State Management Context มีไว้สำหรับการทำ dependency injection เพื่อช่วยหลีกเลี่ยงปัญหา prop drilling อย่างไรก็ตาม เมื่อค่าใน Context เปลี่ยนแปลง ทุกๆ consumer จะถูก re-render ใหม่ทั้งหมด ดังนั้นอย่าใส่ global state ทั้งหมดไว้ใน provider เดียวกัน แต่ควรแยก context ตามวัตถุประสงค์การใช้งาน
รูปแบบขั้นสูง
• useReducer: ใช้สำหรับ state machine ที่มีความซับซ้อน แทนที่จะใช้ useState หลายๆ ตัว
• startTransition: ใช้เพื่อรักษาความลื่นไหลของ UI ในระหว่างที่มีการอัปเดตข้อมูลจำนวนมาก
• useDeferredValue: ใช้เพื่อหน่วงเวลาการอัปเดต UI ที่ใช้ทรัพยากรสูงในขณะที่ผู้ใช้กำลังพิมพ์
เขียนโค้ดให้สะอาดด้วยการย้าย logic ไปไว้ใน custom hooks คอมโพเนนต์ที่มีความยาวถึง 1,200 บรรทัดนั้นดูแลรักษายาก แต่การใช้ hook ขนาดเล็ก 5 ตัวที่แยก logic ออกจากกันจะช่วยให้ขยายระบบได้ง่ายกว่า
แหล่งที่มา: https://dev.to/jagadeesh_008/how-advanced-react-developers-should-think-about-hooks-102l