ความแตกต่างระหว่าง useMemo และ useCallback

Supawadee Khamnuengsithi
20Scoops CNX
Published in
2 min readJul 12, 2021

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

Photo by Christin Hume on Unsplash

ทุกคนทราบมั้ยว่า โดยปกติแล้วทุกคำสั่งใน Component จะสร้างใหม่และทำงานใหม่ทุกครั้งที่มีการเรียก Render ซึ่งการทำเช่นนี้ Memory ในเครื่องก็จะถูก Allocated เพื่อทำงานคำสั่งนั้น ๆ ซึ่งคำสั่งบางอย่างเราก็ไม่ต้องการที่จะต้องสร้างใหม่หรือเรียกซ้ำ ๆใช่มั้ยล่ะ แล้วจะทำยังไงเพื่อป้องกันไม่ให้ Memory ถูกใช้งานโดยไม่จำเป็น ทำให้ เกิด Memory Leak ได้ 💪

หรือ อธิบายในอีกกรณีนึง เช่น เรามีคำสั่งที่ใช้เวลาในการคอมไพล์นาน แต่อยากใช้แค่ครั้งเดียวหรือใช้เฉพาะตอนที่อยากใช้เท่านั้นแต่ตัว Component เราดันสร้างและรันใหม่ในทุก ๆ ครั้งที่ Re-Render ทำให้แอพของเราทำงานช้าไปซะงั้น

ลองรันบน Expo: https://snack.expo.io/@green20/example

ตัวอย่างโค้ดให้เข้าใจได้ง่ายขึ้น เมื่อรันโค้ดนี้ จะเห็นได้ว่าถ้าหาก กดปุ่ม Up/Down Button จะเกิดการ Re-Render ใหม่ซึ่งบรรทัด let randomNumber = Math.random()ก็จะถูกสร้างขึ้นใหม่ด้วย ในกรณีนี้อยากให้เห็นภาพชัดขึ้นเลยใช้ การ Random Number โดยถ้าหากเป็นการคำนวณที่ยากกว่านี้ล่ะ ก็ต้องถูกคำนวณใหม่โดยที่เรายังไม่ได้ใช้มันใช่มั้นล่ะ

จึงมี useMemo และ useCallback เพื่อมาช่วยแก้ปัญหาเหล่านี้

useMemo

useMemo หลักการทำงานก็คือ จะทำการ Cache ข้อมูลเพื่อจำค่าไว้ในหน่วยความจำแคช (Cache Memory) โดยฟังก์ชันจะถูกเรียกใช้งานในครั้งแรกของการ Render และเมื่อค่ามีการเปลี่ยนแปลงเท่านั้น

มาดูโครงสร้างของ useMemo กันก่อน ฟังก์ชัน useMemo จะรับค่าตัวแปร 2 ค่า คือ Fuction และ Array

  1. Function ก็ ฟังก์ชันอ่ะแหละ จะทำอะไรก็แล้วแต่ แต่สุดท้าย Return ค่าที่จะให้ useMemo มันจำด้วย (สำคัญเลย!) เพราะ useMemo เนี่ยมันจะต้อง Return ค่าเป็น Value เท่านั้น
  2. Array จะเก็บตัวแปรทั้งหมดที่เมื่อตัวแปรพวกนี้เปลี่ยนแล้วจะเรียกใช้งานฟังก์ชัน

จาก Code ด้านบน ค่าตัวแปร randomNumberจะถูก Initial ครั้งแรกและจะถูกเปลี่ยนก็ต่อเมื่อเรากดปุ่ม Random เท่านั้นเพราะ ถ้าไล่จากโค้ดคือ เมื่อกดปุ่มแล้วตัวแปร isRandom จะเปลี่ยน และส่งผลให้ useMemo ถูกเรียกใช้นั่นเอง

ลองรันบน Expo : https://snack.expo.io/@green20/usememo

ผลลัพท์ที่เห็นชัด ๆ เลยก็คือไม่ว่าจะกดปุ่มไหนก็ตามค่า Random ที่ไม่ได้ใช้ useMemo จะเปลี่ยนไปเรื่อย ๆ เนื่องจากการ Re-Render ของ Component ส่วนค่า Random ที่มาจาก การใช้ useMemo จะเปลี่ยนก็ต่อเมื่อค่าตัวแปรใน Array มีการเปลี่ยนแปลงเท่านั้น เท่านี้ก็เห็นความสามารถของ useMemo แล้วใช่มั้ยล่ะ

useCallback

useCallback มีหลักการทำงานคล้าย ๆ กับ useMemo เลย คือจะจำการทำงานของ “Function” ไว้ในหน่วยความจำแคช และจะถูกเรียกเมื่อค่าตัวแปรที่เซตไว้มีการเปลี่ยนแปลงหรือเมื่อฟังก์ชันถูกเรียกใช้ แต่ไม่ถูกเรียกตอน Re-Render เราจะต้องเรียกเองนะ โดยลักษณะโครงสร้างก็คือเหมือนกับ useMemo เป๊ะ! เอ๊าาา แล้วต่างกันตรงไหนล่ะ

useCallback จะต่างออกไปตรงที่เป็นฟังก์ชันที่สามารถ Return เป็นฟังก์ชันได้ เอ๊ะ งง มั้ย คือนางจะสามารถทำตัวเป็นฟังก์ชันได้เลยคือ รับ Parameters ได้ ทำตัวเป็น Void ได้ (ไม่ต้อง Return อะไร) และทำการเรียกใช้เหมือนฟังก์ชันทั่วไปได้นั่นเอง

จากโค้ดถูกเปลี่ยนนิดหน่อยก็คือ ฟังก์ชัน randomFunction จะรับ Parameter คือ number โดยมื่อกดปุ่ม Random แล้วฟังก์ชัน randomFunction จะถูกเรียก โดยที่ฟังก์ชันนี้ Return ค่า Random ตั้งแต่ 0 ถึง number ที่ตั้งไว้

ลองรันบน Expo : https://snack.expo.io/@green20/usecallback

Conclusion

จะเห็นได้ว่าวัตถุประสงค์ของ useMemo และ useCallback จะหลักการที่เหมือนกัน โดยจะแตกต่างกันที่ Return Type ของ Function โดย useMemo จะ Return Value ส่วน useCallback จะทำการ Return Fucntion และเจ้าสองตัวนี้เกิดมาเพื่อให้เราทำการ Optimize Code และป้องกันการเกิด Memory Leak 😎

--

--