React.memo
React апп томрох тусам гүйцэтгэл чухал болж ирдэг. Энэ хичээлд React.memo ашиглан component-ийг хэрэггүй дахин рендерлэхээс хэрхэн хамгаалахыг сурна. Эхлэгчдэд хэцүү сэдэв мэт санагдаж болох ч жишээнүүдийг дагаж сурвал маш хялбар!
Яагаад React.memo хэрэгтэй вэ?
React-д parent component рендерлэгдэх бүрт түүний бүх child component-ууд ч дахин рендерлэгддэг — тэдний props өөрчлөгдсөн эсэхийг үл харгалзан. Энэ нь жижиг аппад асуудал биш боловч том аппад гүйцэтгэлийг удаашруулдаг.
function Parent() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>+1</button>
{/* count өөрчлөгдөх бүрт Child ч рендерлэгдэнэ */}
<Child name="Болд" />
</div>
);
}
function Child({ name }) {
console.log("Child рендерлэгдлээ");
return <p>Сайн уу, {name}!</p>;
}
Дээрх жишээнд Child-д дамжигч name prop хэзээ ч өөрчлөгддөггүй. Гэсэн ч count өөрчлөгдөх бүрт Child дахин рендерлэгдэнэ. Энэ бол хэрэггүй ажил.
React.memo ашиглах нь
React.memo нь component-ийг "memorize" хийдэг — props өөрчлөгдөөгүй бол дахин рендерлэхгүй.
import { memo } from "react";
// memo() дотор component-оо боож өгнө
const Child = memo(function Child({ name }) {
console.log("Child рендерлэгдлээ");
return <p>Сайн уу, {name}!</p>;
});
function Parent() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>+1 ({count})</button>
{/* name prop өөрчлөгдөөгүй тул Child дахин рендерлэгдэхгүй */}
<Child name="Болд" />
</div>
);
}
Одоо count өөрчлөгдөхөд Child дахин рендерлэгдэхгүй — учир нь name="Болд" өөрчлөгдөөгүй байна.
React.memo хэзээ ашиглах вэ?
React.memo бүх газар хэрэглэх шаардлагагүй. Дараах нөхцөлд л хэрэглэх нь зүйтэй:
// ✅ Зөв — рендерлэх нь үнэтэй, props тогтмол
const HeavyChart = memo(function HeavyChart({ data }) {
// их тооцоолол...
return <canvas />;
});
// ✅ Зөв — жагсаалтын мөр, олон удаа рендерлэгдэнэ
const ListItem = memo(function ListItem({ item }) {
return <li>{item.title}</li>;
});
// ❌ Хэрэггүй — props байнга өөрчлөгдөж байвал memo тус болохгүй
const Counter = memo(function Counter({ count }) {
return <p>{count}</p>;
});
React.memo нь props-ийг гадаргуугаар харьцуулдаг (shallow comparison). Тиймээс object эсвэл array props байвал useMemo эсвэл useCallback-тай хослуулан хэрэглэх хэрэгтэй болдог — дараагийн хичээлүүдэд үүнийг сурна.
Жишээ: тооцоолол ихтэй жагсаалт
import { memo, useState } from "react";
// Энэ component-ийг memo-гоор хамгаална
const ProductCard = memo(function ProductCard({ product }) {
console.log(`${product.name} рендерлэгдлээ`);
return (
<div style={{ border: "1px solid #ccc", padding: "8px", margin: "4px" }}>
<h3>{product.name}</h3>
<p>{product.price}₮</p>
</div>
);
});
export default function Shop() {
const [search, setSearch] = useState("");
const products = [
{ id: 1, name: "Гар утас", price: 800000 },
{ id: 2, name: "Зөөврийн компьютер", price: 2500000 },
{ id: 3, name: "Чихэвч", price: 150000 },
];
return (
<div>
<input
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Хайх..."
/>
{/* search өөрчлөгдөхөд ProductCard-ууд дахин рендерлэгдэхгүй */}
{products.map((p) => (
<ProductCard key={p.id} product={p} />
))}
</div>
);
}
Console-д харвал ProductCard-ууд зөвхөн эхний рендерт л log хэвлэнэ — search бичих бүрт дахин хэвлэгдэхгүй. React.memo ажиллаж байна!
Дараагийн хичээлд:
useMemo hook-ийг сурна — component дотор хийгддэг үнэтэй тооцооллын үр дүнг хэрхэн санаж үлдэхийг ойлгоно. React.memo ба useMemo хоёрын ялгааг тодруулна.