⊗jsrtPmHkUCb 16 of 47 menu

ฮุคปรับปรุงประสิทธิภาพ useCallback ใน React

ในบทเรียนนี้ เราจะมาดูฮุคสำหรับปรับปรุงประสิทธิภาพตัวต่อไป คือ useCallback

ฮุค useCallback คล้ายกับ API useMemo ความแตกต่างคือตัวแรก แคชค่าต่างๆ ระหว่างการรีเรนเดอร์หน้า ส่วนตัวที่สองคือ callback สิ่งนี้ทำให้เราไม่ต้องเรียกฟังก์ชันที่ใช้ทรัพยากรสูง เมื่อไม่จำเป็น และสามารถ ใช้ได้เมื่อ ส่งผ่านฟังก์ชัน ไปยังคอมโพเนนต์ลูก

ลองมาทำความเข้าใจกันมากขึ้นผ่านตัวอย่าง เริ่มจากสร้างคอมโพเนนต์ App และสร้าง state num ในนั้น:

const [num, setNum] = useState(0);

ให้เรามีปุ่ม เมื่อคลิก num จะเพิ่มขึ้น 1 และมีย่อหน้า ซึ่งเราจะ แสดงค่า num:

return ( <div> <button onClick={() => setNum(num + 1)}>คลิก</button> <p>จำนวนคลิก: {num}</p> </div> );

และตอนนี้ สมมติว่าใน App มีการแสดงรายการอื่น พร้อมไอเท็ม ซึ่งเราจะเพิ่มเติม โดยการกดปุ่มอีกปุ่มหนึ่ง สำหรับเก็บ ไอเท็มของรายการนี้ เราจะสร้าง state items:

const [items, setItems] = useState([]);

จากนั้นเขียนฟังก์ชัน addItem เพื่อเพิ่มพวกมัน:

function addItem() { setItems([...items, 'ไอเท็มใหม่']); }

ตอนนี้มาเขียนโค้ดสำหรับแสดง ไอเท็มของรายการและแยกมันออกไปเป็นคอมโพเนนต์ลูก Items ซึ่งจะรับอาร์เรย์ของไอเท็ม และฟังก์ชันสำหรับเพิ่มพวกมันผ่าน props อย่าลืม เพิ่มการแสดงผลในคอนโซล เพื่อให้เห็น ว่าเมื่อไหร่ที่ Items ของเรา จะถูกรีเรนเดอร์:

function Items({ items, addItem }) { const result = items.map((item, index) => { return <p key={index}>{item}</p>; }); console.log('Items render'); return ( <div> <h3>ไอเท็มของเรา</h3> {result} <button onClick={addItem}>เพิ่มไอเท็ม</button> </div> ); } export default Items;

ให้เราใส่ Items ที่ส่วนท้ายของคอมโพเนนต์ App และส่งผ่านอาร์เรย์ items และฟังก์ชันสำหรับเพิ่ม ไอเท็ม addItem ไปให้:

return ( <> <div> <button onClick={() => setNum(num + 1)}>คลิก</button> <p>จำนวนคลิก: {num}</p> <br /> </div> <Items items={items} addItem={addItem} /> </> );

และตอนนี้ลองกดปุ่มต่างๆ และตรวจสอบว่า num เพิ่มขึ้นและ ไอเท็มใหม่ถูกเพิ่มเข้าไปในรายการ และเมื่อเปิดคอนโซล เราจะเห็นว่า รายการของเราถูกรีเรนเดอร์ทุกครั้ง แม้ว่าเราจะคลิกที่ปุ่ม ที่เพิ่ม num

ถ้ารายการของเราเล็ก ก็โอเค แต่ถ้ามันมีขนาดใหญ่และมีอะไรอีกมากมายในนั้นล่ะ? ไม่ใช่ปัญหา - คุณอาจพูด เพราะในบทเรียนที่แล้ว เราได้เรียนรู้ API memo เพื่อหลีกเลี่ยงการรีเรนเดอร์คอมโพเนนต์ที่ไม่จำเป็น

งั้นลองมาห่อคอมโพเนนต์ Items ของเราด้วย memo แล้วน่าจะเรียบร้อย โดยสามารถทำได้เลยที่ การ export Items:

export default memo(Items);

อย่าลืม import memo:

import { memo } from 'react';

และตอนนี้เปิดคอนโซลและลองกด ปุ่มดู ความพยายามทั้งหมดสูญเปล่า! เรา ใช้ memoization กับคอมโพเนนต์แล้ว แต่เมื่อกด ปุ่ม 'คลิก' คอมโพเนนต์ Items ยังคง ถูกรีเรนเดอร์ทุกครั้ง

ปัญหาคือ เมื่อคอมโพเนนต์แม่ ถูกรีเรนเดอร์ ฟังก์ชันของมัน จะถูกสร้างใหม่ - นี่รวมถึง ฟังก์ชัน addItem ของเราด้วย ซึ่งเราส่งไปยัง Items

นี่คือช่วงเวลาที่ฮุค useCallback จะช่วยเราได้ ลองมาใช้งาน มันดู เริ่มจาก import มันเข้าไปใน App:

import { useCallback } from 'react';

จากนั้นปรับเปลี่ยนการประกาศฟังก์ชันธรรมดา addItem เป็น Function Expression, ระบุเป็น พารามิเตอร์แรกสำหรับ useCallback เป็นฟังก์ชันของเราในรูปแบบ callback พารามิเตอร์ที่สอง ในวงเล็บเหลี่ยมให้ระบุ dependencies - ตัวแปร reactive ทั้งหมด ที่เกี่ยวข้องในฟังก์ชัน ในกรณีของเรา คืออาร์เรย์ items:

const addItem = useCallback(() => { setItems(() => [...items, 'ไอเท็มใหม่']); }, [items]);

เรียบร้อย! ด้วยวิธีนี้เราได้แคช ฟังก์ชันแล้ว ลองกดปุ่มอีกครั้งและ ดูว่าตอนนี้เมื่อกดปุ่ม 'คลิก' คอมโพเนนต์ลูกของเราไม่ ถูกรีเรนเดอร์

สร้างคอมโพเนนต์ App ใส่ ย่อหน้าที่มีข้อความเข้าไป สร้าง state ด้วยค่าเริ่มต้น 'ข้อความ' และแสดงผลในย่อหน้า ให้เมื่อคลิก บนย่อหน้า จะมีเครื่องหมายอัศเจรีย์ ถูกเติมต่อท้ายข้อความ

สร้างคอมโพเนนต์ลูก Products ซึ่งจะมีปุ่มสำหรับเพิ่ม สินค้าใหม่ วางมันใน App ในคอมโพเนนต์แม่ให้สร้าง state ด้วยอาร์เรย์ของสินค้าและฟังก์ชันเพิ่ม สินค้าใหม่ ส่งพวกมัน เป็น props ไปยังคอมโพเนนต์ลูก แสดงผลอาร์เรย์ที่ส่งมา ในรูปแบบรายการ ul

ใน Products ให้แสดงผลข้อความ 'products render' ในคอนโซล ห่อ Products ด้วย memo ลองคลิกบนย่อหน้าและปุ่ม ตรวจสอบ ว่าหากคลิกบนย่อหน้า คอมโพเนนต์ลูก ยังคงถูกรีเรนเดอร์

แคชฟังก์ชันสำหรับเพิ่ม สินค้า โดยห่อมันด้วยฮุค useCallback ลองคลิกบนย่อหน้าและปุ่ม ตรวจสอบ ว่าหากคลิกบนย่อหน้า คอมโพเนนต์ลูก จะไม่ถูกรีเรนเดอร์อีกต่อไป

ไทย
AfrikaansAzərbaycanБългарскиবাংলাБеларускаяČeštinaDanskDeutschΕλληνικάEnglishEspañolEestiSuomiFrançaisहिन्दीMagyarՀայերենIndonesiaItaliano日本語ქართულიҚазақ한국어КыргызчаLietuviųLatviešuМакедонскиMelayuမြန်မာNederlandsNorskPolskiPortuguêsRomânăРусскийසිංහලSlovenčinaSlovenščinaShqipСрпскиSrpskiSvenskaKiswahiliТоҷикӣTürkmenTürkçeЎзбекOʻzbekTiếng Việt
เราใช้คุกกี้สำหรับการทำงานของเว็บไซต์ การวิเคราะห์ และการปรับเนื้อหาให้เหมาะสมส่วนบุคคล การประมวลผลข้อมูลเกิดขึ้นตาม นโยบายความเป็นส่วนตัว.
ยอมรับทั้งหมด ปรับแต่ง ปฏิเสธ