useMemo bilan memoizatsiya qilish
React.memo
va useMemo
ikkalasi ham memoizatsiya vositalaridir, lekin ularning ishlatilish maqsadlari tubdan farq qiladi. React.memo
butun komponentni memoizatsiya qiladi, uni qayta render qilishdan saqlaydi. useMemo
esa komponent ichidagi alohida hisoblashlarni memoizatsiya qiladi, murakkab hisoblashlarni oldini olish va natija uchun izchil referensni saqlab qolish uchun qo’llaniladi.
useMemo’ga misol
Keling, useMemo
bilan qisqacha tanishamiz. Quyidagi komponentni ko’rib chiqamiz:
const People = ({ unsortedPeople }) => {
const [name, setName] = useState("");
const sortedPeople = unsortedPeople.sort((a, b) => b.age - a.age);
// ... komponentning qolgan qismi
};
Ushbu komponent bizning ilovamizni sekinlashtirishi mumkin, chunki unda saralash operatsiyasi mavjud. Saralash operatsiyasining vaqt murakkabligi odatda o’rtacha va eng yomon holatlarda O(n log n)
ga teng. Agar bizda, masalan, bir million odam bo’lsa, bu har bir renderda sezilarli hisoblash yukini keltirib chiqarishi mumkin. Computer science’da saralash operatsiyasining samaradorligi asosan elementlar soni, n, bilan belgilanadi, shuning uchun O(n log n)
vaqt murakkabligiga ega.
Buni optimizatsiya qilish uchun, useMemo
hook’idan foydalanib, har renderda odamlar ro’yxatini saralashning oldini olishimiz mumkin, ayniqsa unsortedPeople
massivida o’zgarishlar bo’lmaganda.
Samaradorlik muammosi
Komponentning joriy implementatsiyasi sezilarli darajada samaradorlik muammosini keltirib chiqaradi. Har safar state yangilanganda, ya’ni input maydonida har bir klaviatura bosilishida komponent qayta render qilinadi. Agar kiritilgan ism 5 ta belgidan iborat bo’lsa va ro’yxatimizda 1,000,000 odam bo’lsa, komponent 5 marta qayta render bo’ladi. Har bir renderda ro’yxat saralanadi, bu saralashning vaqt murakkabligi tufayli 1,000,000 × log(1,000,000) operatsiyalarni o’z ichiga oladi. Bu shunchaki 5 ta belgili ism kiritishda ko’plab millionlab operatsiyalarni amalga oshiradi! Yaxshiyamki, ushbu samarasizlikni useMemo
yordamida kamaytirish mumkin, bu saralash operatsiyasi faqat unsortedPeople
massivida o’zgarishlar bo’lganda bajarilishini ta’minlaydi.
Keling, ushbu kodni biroz o’zgartiraylik:
const People = ({ unsortedPeople }) => {
const [name, setName] = useState("");
const sortedPeople = useMemo(
// Original massivni o'zgartirmaslik uchun yoyish(spreading) amalini ishlatamiz
() => [...unsortedPeople].sort((a, b) => b.age - a.age),
[unsortedPeople]
);
return (
<div>
<div>
Ismingizni kiriting:{" "}
<input
type="text"
placeholder="Obinna Ekwuno"
onChange={(e) => setName(e.target.value)}
/>
</div>
<ul>
<h1>Salom, {name}! Mana yoshi bo'yicha saralangan odamlar ro'yxati!</h1>
{sortedPeople.map((p) => (
<li key={p.id}>
{p.name}, yoshi {p.age}
</li>
))}
</ul>
</div>
);
};
Mana, endi ancha yaxshi! Biz sortedPeople
qiymatini useMemo
ning birinchi argumentiga o’tkazilgan funksiyaga o’rab qo’ydik. useMemo
ga berilgan ikkinchi argument esa qiymatlar massivini ifodalaydi, agar bu qiymatlar o’zgarsa, massiv qayta saralanadi. Chunki massivda faqat unsortedPeople
bor, u faqat bir marta saralanadi va har safar odamlar ro’yxati o’zgarganda amalga oshadi — kimdur input maydonida ismni yozganda emas. Bu, useMemo
dan foydalanib, keraksiz qayta renderlarni oldini olishning ajoyib misolidir.