useEffect — asinxron funksiya, fetch bilan ishlash

~20 daq · React · Hooks — Asosiy

To'liq fetch pattern

Server dan ma'lumot olish — eng ko'p uchraydigan useEffect ishlatilishi. Lekin to'g'ri yozish uchun uchta holatni boshqarish kerak: yuklanmoqda, xato, muvaffaqiyat.

function UserRoyxati() {
  const [users, setUsers] = useState([]);
  const [yuklanmoqda, setYuklanmoqda] = useState(true);
  const [xato, setXato] = useState(null);

  useEffect(() => {
    async function olish() {
      try {
        setYuklanmoqda(true);
        setXato(null);

        const res = await fetch('https://jsonplaceholder.typicode.com/users');

        if (!res.ok) {
          throw new Error(`Server xatosi: ${res.status}`);
        }

        const data = await res.json();
        setUsers(data);
      } catch (err) {
        setXato(err.message);
      } finally {
        setYuklanmoqda(false);
      }
    }

    olish();
  }, []);

  if (yuklanmoqda) return <p>Yuklanmoqda...</p>;
  if (xato) return <p>Xato: {xato}</p>;

  return (
    <ul>
      {users.map(u => <li key={u.id}>{u.name}</li>)}
    </ul>
  );
}

Uchta holat:

yuklanmoqda = true  → "Yuklanmoqda..." ko'rsatiladi
xato = "..."        → xato xabari ko'rsatiladi
muvaffaqiyat        → ma'lumot ko'rsatiladi

Parametrga bog'liq so'rov

Qidiruv, filtr, sahifa raqami — bular o'zgarganda yangi so'rov yuborilishi kerak.

function MahsulotQidirish() {
  const [qidiruv, setQidiruv] = useState('');
  const [mahsulotlar, setMahsulotlar] = useState([]);
  const [yuklanmoqda, setYuklanmoqda] = useState(false);

  useEffect(() => {
    if (!qidiruv.trim()) {
      setMahsulotlar([]);
      return;
    }

    const controller = new AbortController();

    async function qidirish() {
      setYuklanmoqda(true);
      try {
        const res = await fetch(
          `/api/mahsulotlar?q=${qidiruv}`,
          { signal: controller.signal }
        );
        const data = await res.json();
        setMahsulotlar(data);
      } catch (err) {
        if (err.name !== 'AbortError') setMahsulotlar([]);
      } finally {
        setYuklanmoqda(false);
      }
    }

    qidirish();

    return () => controller.abort();
  }, [qidiruv]); // qidiruv o'zgarganda qayta so'rov

  return (
    <div>
      <input
        value={qidiruv}
        onChange={e => setQidiruv(e.target.value)}
        placeholder="Qidirish..."
      />
      {yuklanmoqda && <p>Qidirilmoqda...</p>}
      <ul>
        {mahsulotlar.map(m => <li key={m.id}>{m.nomi}</li>)}
      </ul>
    </div>
  );
}

Foydalanuvchi har harf yozganda so'rov ketadi. AbortController eski so'rovni bekor qiladi — faqat oxirgi so'rovning natijasi ko'rsatiladi.


Race condition muammosi

Foydalanuvchi tez-tez filtr o'zgartirsa — bir nechta so'rov ketadi. Qaysi biri oxirgi kelishini bilmaysiz.

So'rov 1 (id=1) → ketdi...
So'rov 2 (id=2) → ketdi...
So'rov 2 → keldi, setUser(user2) ✅
So'rov 1 → keldi, setUser(user1) ❌ — eski ma'lumot ustiga yozdi!

AbortController bu muammoni hal qiladi — dependency o'zgarganda cleanup ishlaydi va eski so'rov bekor qilinadi.

userId = 1 → so'rov boshlandi
userId = 2 → cleanup: so'rov 1 bekor qilindi
           → yangi so'rov boshlandi

Tez-tez uchraydigan xatolar

res.ok ni tekshirmaslik:

// ❌ 404, 500 xatolarda ham data olishga urinadi
const data = await fetch('/api/users').then(r => r.json());

// ✅ Status tekshiriladi
const res = await fetch('/api/users');
if (!res.ok) throw new Error(`${res.status}`);
const data = await res.json();

fetch faqat tarmoq xatosida (internet yo'q) reject qiladi. Server 404 yoki 500 qaytarsa — Promise resolve bo'ladi. res.ok tekshirilmasa — xato sezilmaydi.

Loading state ni boshida false qoldirish:

// ❌ Birinchi render da ma'lumot yo'q, loading ham yo'q
// → bo'sh sahifa ko'rsatiladi
const [yuklanmoqda, setYuklanmoqda] = useState(false);

// ✅ Boshida true — darhol "Yuklanmoqda..." ko'rsatiladi
const [yuklanmoqda, setYuklanmoqda] = useState(true);

Xulosa

useEffect ichida fetch:
  1. async funksiya ichida yozing
  2. try/catch/finally — uch holat
  3. res.ok tekshiring
  4. AbortController — cleanup da bekor qiling
  5. dependency array to'g'ri to'ldiring

Bu pattern ko'p takrorlanadi. Keyinchalik TanStack Query bu ishni avtomatik qiladi — loading, error, caching, refetch hammasi tayyor. Lekin asosini tushunish muhim.


Keyingi dars

13-dars: useRef — DOM ga murojaat, focus, scroll