เรียนรู้ว่าเมื่อไหร่ React.memo, useMemo และ useCallback จะเร่งความเร็วแอปของคุณได้จริง และเมื่อไหร่ที่มันทำให้ซับซ้อนขึ้นโดยเปล่าประโยชน์
เปิดบทเรียนนี้ใน Kodokonเมื่อ component หนึ่ง re-render ลูกทั้งหมดของมันจะ re-render โดยปริยาย ไม่ว่า props ของพวกมันจะเปลี่ยนหรือไม่ นั่นไม่ใช่โศกนาฏกรรม: การ render จะแตะ DOM ก็ต่อเมื่อผลลัพธ์เปลี่ยนเท่านั้น Memoization จะมีความหมายเมื่อการ render บ่อยๆ มาพบกับ subtree ที่มีค่าใช้จ่ายสูง สามเครื่องมือ สามเป้าหมาย: React.memo ข้ามการ render ของ component หาก props ของมันเท่ากันแบบตื้น, useMemo แคช ค่า ที่คำนวณได้, useCallback แคช ฟังก์ชัน ทั้งสามอาศัยความเท่ากันของ reference
import { memo } from "react";
const Row = memo(function Row({ item, onSelect }) {
return (
<li onClick={() => onSelect(item.id)}>{item.label}</li>
);
});โซ่จะแข็งแรงเท่ากับข้อที่อ่อนที่สุดของมัน หาก prop เพียงตัวเดียวได้รับ reference ใหม่ในทุก render - arrow function แบบ inline, object หรือ array literal - การเปรียบเทียบของ memo จะล้มเหลวและ component ก็ re-render อยู่ดี useCallback ทำให้ reference ของฟังก์ชันคงที่เพื่อให้การเปรียบเทียบสำเร็จ
import { useCallback } from "react";
function List({ items }) {
const handleSelect = useCallback((id) => {
console.log("selected:", id);
}, []);
return (
<ul>
{items.map((item) => (
<Row
key={item.id}
item={item}
onSelect={handleSelect}
/>
))}
</ul>
);
}useMemo มีการใช้งานที่ชอบธรรมอยู่สองแบบ: หลีกเลี่ยง การคำนวณที่มีค่าใช้จ่ายสูงจริงๆ (การเรียงลำดับหรือรวมข้อมูลหลายพันรายการ) และ ทำให้ reference คงที่ ที่ถูกใช้โดยลูกที่ถูก memoize หรือถูกระบุใน dependency ของ effect สำหรับการคำนวณเล็กน้อย แคชมีค่าใช้จ่ายมากกว่าที่มันประหยัดได้: การเปรียบเทียบ dependency, หน่วยความจำที่ถูกกันไว้, การอ่านที่หนักขึ้น
import { useMemo } from "react";
function Stats({ orders }) {
const total = useMemo(() => {
return orders.reduce(
(sum, order) => sum + order.amount,
0
);
}, [orders]);
return <p>Total: {total} €</p>;
}