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 useMemoning birinchi argumentiga o’tkazilgan funksiyaga o’rab qo’ydik. useMemoga 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, useMemodan foydalanib, keraksiz qayta renderlarni oldini olishning ajoyib misolidir.