Skip to main content

การใช้งานและความแตกต่างระหว่าง useMemo และ useCallback ของ React Hooks

· 3 min read
Kongvut Sangkla

Intro

สวัสดีครับ บทความนี้จะแนะนำแนวทางการใช้งาน React Hooks ที่ชื่อ useMemo และ useCallback คืออะไร มีความสำคัญอย่างไร ช่วยเพิ่มประสิทธิภาพลดการ Render ของ React ที่หนักหน่วงอย่างไร ควร Refactor อย่างไร มาดูกันเลยครับ 😍

TL; DR;

  • useMemo คือการ Cache ค่า Value ถูกเรียกครั้งแรกเมื่อมีการ Render และครั้งต่อไปเมื่อมีการ Re-Render และ ค่าใน Array deps มีการเปลี่ยนแปลง โดย Return ออกเป็นค่า Value
  • useCallback คือการ Cache Function ไม่ ถูกเรียกครั้งแรกเมื่อมีการ Render โดยจะถูกเรียกก็ต่อเมื่อสั่ง Call ฟังก์ชัน และ ค่าใน Array deps มีการเปลี่ยนแปลง โดย Return ออกเป็น Function

Imgur

เริ่มกันเลย

ปัญหา Re-Render

ปัญหาการ Re-Render นั้นเป็นปัญหาใหญ่ ที่ทำให้เกิดการ Render ที่หนักหน่วง ตามปกติทุกการ Render จะเกิดการจอง Memory (Memory allocation) และบางทีการ Render Component ซ้ำ ๆ เกินความจำเป็นอาจจะทำให้เกิดการจัดสรรหน่วยความจำอย่างไม่ถูกต้อง (Memory Leak) ได้

แก้ปัญหาด้วย useMemo

ในตัวอย่างนี้จะใช้การวิธีการแสดงค่า Timestamp ของฟังก์ชัน Date เป็นกรณียกตัวอย่างเมื่อหน้าเว็บถูก Re-Render ในแต่ละครั้ง

Live Editor
Result
Loading...

แบบไม่ใช้ useMemo

  • Timestamp แสดงครั้งแรกเมื่อมีการ Render
  • Timestamp แสดงอีกครั้งเมื่อมีการ Re-Render (Number หรือ Some Value เปลี่ยนแปลง)
  • เป็นตัวอย่างกรณีการ Re-Render เกินความจำเป็น

แบบใช้ useMemo

  • Timestamp แสดงครั้งแรกเมื่อมีการ Render
  • Timestamp แสดงอีกครั้งเมื่อมีการ Re-Render และ ค่า Some Value มีการเปลี่ยนแปลงเท่านั้น
  • เป็นตัวอย่างกรณีการ Re-Render เฉพาะที่จำเป็น

แก้ปัญหาด้วย useCallback

ในตัวอย่างนี้จะใช้การวิธีการแสดงค่า Timestamp ของฟังก์ชัน Date เป็นกรณียกตัวอย่างเมื่อหน้าเว็บถูก Re-Render ในแต่ละครั้ง

Live Editor
Result
Loading...

แบบไม่ใช้ useCallback

  • Timestamp แสดงครั้งแรกเมื่อมีการ Render
  • Timestamp แสดงอีกครั้งเมื่อมีการ Re-Render (Number หรือ Some Value เปลี่ยนแปลง)
  • เป็นตัวอย่างกรณีการ Re-Render เกินความจำเป็น

แบบใช้ useCallback

  • Timestamp ไม่แสดงครั้งแรกเรียกเมื่อมีการ Render (จะแสดงเมื่อเราสั่ง Call ฟังก์ชันเอง)
  • Timestamp แสดงเมื่อสั่ง Call ฟังก์ชัน และ ค่าใน Some Value มีการเปลี่ยนแปลงเท่านั้น
  • เป็นตัวอย่างกรณีการ Re-Render เฉพาะที่จำเป็น

สรุป

หลักการของ useMemo คือการ Cache ข้อมูลไว้

  • ถูกเรียกครั้งแรกเมื่อมีการ Render
  • ถูกเรียกอีกครั้งเมื่อมีการ Re-Render และ ค่าใน Array deps มีการเปลี่ยนแปลง
  • Return ออกเป็นค่า Value

หลักการของ useCallback คือการ Cache ฟังก์ชันไว้

  • ไม่ ถูกเรียกเมื่อมีการ Render (จะถูกเรียกเมื่อเราสั่ง Call ฟังก์ชันเอง)
  • ถูกเรียกอีกครั้งเมื่อสั่ง Call ฟังก์ชัน และ ค่าใน Array deps มีการเปลี่ยนแปลง
  • Return ออกเป็น Function
note

useCallback(fn, deps) จะเท่ากับ useMemo(() => fn, deps)

ทั้งสองตัวมีการทำงานที่คล้ายกัน และแตกต่างกันนิดหน่อย แต่ทั้งสองสามารถช่วยเพิ่มประสิทธิภาพเพื่อช่วยลดการ Re-Render ในบางกรณีที่เกินความจำเป็นได้ และต้องเลือกใช้ตามความเหมาะสมดังนี้

  • เมื่อ Client ใช้ Device สเปคเครื่องไม่ค่อยแรง React อาจจะหน่วงและช้ามาก ๆ ซึ่งการ Optimize render ก็อาจจะช่วยไปได้เยอะมาก ๆ
  • useMemo ใช้เมื่อถ้ามีการคำนวณอะไรที่ใช้เวลานานมาก ๆ และต้องการทำ Memorizes ไว้ แต่ในการกลับกัน ไม่ควรใช้กับการคำนวณง่าย ๆ เช่น 1 + 1 เพราะเป็นปกติจะได้ผลลัพธ์เร็วอยู่แล้ว และอาจจะทำให้เกิด Overhead เปล่า ๆ
  • เมื่อมี Component ซับซ้อนและเยอะ และมี Logic เยอะ ที่เป็น Parent Child หลายชั้น ถ้าไม่มีการทำ Optimize render อาจจะช้าและค้างได้เลย
  • Input Form ที่มีฟิลด์เยอะ ๆ ถ้าไม่คำนึงเรื่องพวกนี้ ถ้าเวลาพิมพ์ เร็ว ๆ จะสะดุดมาก ๆ

อ้างอิงและรายละเอียดอื่น ๆ

Loading...