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

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

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

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

App.jsxconst [num, setNum] = useState(0);

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

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

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

App.jsxconst [items, setItems] = useState([]);

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

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

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

Items.jsxfunction 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 ไปให้:

App.jsxreturn (
  <>
    <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:

Items.jsxexport default memo(Items);

อย่าลืม import memo:

Items.jsximport { memo } from 'react';

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

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

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

App.jsximport { useCallback } from 'react';

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

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

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

Задание 1

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

Задание 2

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

Задание 3

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

Задание 4

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