fetch bilan API — yuklanish, xato, bekor qilish
Muammodan boshlaylik
Mahsulotlar endi kodda emas — serverda. Ilova ularni internetdan olishi kerak. Lekin mobil tarmoq — vebdan ancha "og'irroq":
- Metro tunnelida internet yo'qoladi
- 3G da so'rov 5 soniya davom etadi
- Foydalanuvchi ekrandan chiqib ketdi, javob esa keyin keldi — va mavjud bo'lmagan ekranni yangilashga urinadi
Har bir so'rov uchun uchta holat kerak: yuklanmoqda, xato, ma'lumot.
fetch asoslari
React Native da fetch — xuddi brauzerdagi kabi:
const javob = await fetch('https://dummyjson.com/products?limit=20');
const data = await javob.json();
POST:
const javob = await fetch('https://api.dokon.uz/buyurtmalar', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ mahsulotId: 5, soni: 1 }),
});
[!WARNING]
fetchHTTP xato kodlarida (404, 500) xato tashlamaydi — faqat tarmoq uzilganda.javob.okni har doim tekshiring.
To'liq naqsh: uchta holat
import { useEffect, useState } from 'react';
import { FlatList, Text, View, ActivityIndicator, Pressable } from 'react-native';
type Mahsulot = { id: number; title: string; price: number; thumbnail: string };
export default function Katalog() {
const [mahsulotlar, setMahsulotlar] = useState<Mahsulot[]>([]);
const [yuklanmoqda, setYuklanmoqda] = useState(true);
const [xato, setXato] = useState<string | null>(null);
async function yukla(signal?: AbortSignal) {
setYuklanmoqda(true);
setXato(null);
try {
const javob = await fetch('https://dummyjson.com/products?limit=20', { signal });
if (!javob.ok) throw new Error(`Server xatosi: ${javob.status}`);
const data = await javob.json();
setMahsulotlar(data.products);
} catch (e) {
if ((e as Error).name === 'AbortError') return; // ekrandan chiqildi — e'tiborsiz
setXato("Ma'lumotni yuklab bo'lmadi. Internet aloqasini tekshiring.");
} finally {
setYuklanmoqda(false);
}
}
useEffect(() => {
const ctrl = new AbortController();
yukla(ctrl.signal);
return () => ctrl.abort(); // ekran yopilsa — so'rovni bekor qilish
}, []);
if (yuklanmoqda && mahsulotlar.length === 0) {
return <View style={{ flex: 1, justifyContent: 'center' }}><ActivityIndicator size="large" /></View>;
}
if (xato) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', gap: 12, padding: 24 }}>
<Text style={{ textAlign: 'center' }}>{xato}</Text>
<Pressable onPress={() => yukla()}><Text style={{ color: '#0284c7', fontWeight: '600' }}>Qayta urinish</Text></Pressable>
</View>
);
}
return (
<FlatList
data={mahsulotlar}
keyExtractor={(m) => String(m.id)}
renderItem={({ item }) => <Text style={{ padding: 16 }}>{item.title} — ${item.price}</Text>}
refreshing={yuklanmoqda}
onRefresh={() => yukla()}
/>
);
}
Har bir holat uchun aniq ekran:
- Yuklanmoqda — spinner (yoki skeleton, 47-dars)
- Xato — tushunarli xabar va "Qayta urinish" tugmasi. Foydalanuvchini "o'lik" ekranda qoldirmang
- Ma'lumot — ro'yxat, pull-to-refresh bilan
AbortController
Foydalanuvchi ekranni ochdi va darhol orqaga qaytdi. So'rov hali ketmoqda. Javob kelganda setMahsulotlar — yo'q bo'lgan komponentni yangilashga urinadi. AbortController + cleanup funksiyasi — ekran yopilganda so'rov bekor qilinadi.
API qatlami
Har bir ekranda fetch, headerlar, token, xato tekshiruvi — takrorlanish. Bitta joyga:
// lib/api.ts
import * as SecureStore from 'expo-secure-store';
const BASE_URL = process.env.EXPO_PUBLIC_API_URL ?? 'https://api.dokon.uz';
export class ApiXato extends Error {
constructor(public status: number, message: string, public data?: unknown) {
super(message);
}
}
export async function api<T>(yol: string, options: RequestInit = {}): Promise<T> {
const token = await SecureStore.getItemAsync('token');
const javob = await fetch(`${BASE_URL}${yol}`, {
...options,
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...options.headers,
},
});
if (javob.status === 204) return undefined as T;
const data = await javob.json().catch(() => null);
if (!javob.ok) {
throw new ApiXato(javob.status, data?.xato ?? `Xato ${javob.status}`, data);
}
return data as T;
}
// Qulay yordamchilar
export const apiGet = <T,>(yol: string) => api<T>(yol);
export const apiPost = <T,>(yol: string, body: unknown) =>
api<T>(yol, { method: 'POST', body: JSON.stringify(body) });
Ishlatish:
const mahsulotlar = await apiGet<Mahsulot[]>('/mahsulotlar?toifa=1');
const buyurtma = await apiPost<{ id: number }>('/buyurtmalar', { mahsulotId: 5, soni: 1 });
Muhit o'zgaruvchilari
# .env
EXPO_PUBLIC_API_URL=https://api.dokon.uz
process.env.EXPO_PUBLIC_API_URL
EXPO_PUBLIC_prefiksi — Expo shu o'zgaruvchilarni ilovaga qo'shadi- Maxfiy kalitlarni bu yerga qo'ymang: ilova ichidagi har qanday narsani ochib ko'rish mumkin. Maxfiy kalitlar — faqat serverda
localhost tuzog'i
Kompyuteringizdagi backend http://localhost:3000 da. Telefonda localhost — telefonning o'zi, kompyuter emas.
EXPO_PUBLIC_API_URL=http://192.168.1.10:3000 ← kompyuterning lokal IP si
Android emulyatorda kompyuter — 10.0.2.2. iOS simulatorda localhost ishlaydi. Va Android http:// (shifrlanmagan) so'rovlarni production da bloklaydi — haqiqiy server — faqat https.
Tarmoq holatini tekshirish
npx expo install @react-native-community/netinfo
import NetInfo from '@react-native-community/netinfo';
const holat = await NetInfo.fetch();
if (!holat.isConnected) {
setXato("Internet aloqasi yo'q");
return;
}
36-darsda offline rejimni batafsil ko'ramiz.
Nima uchun shunday?
Nima uchun har bir ekranda bunchalik ko'p kod — yuklanish, xato, bekor qilish, qayta urinish?
Chunki mobil tarmoq ishonchsiz — bu istisno emas, odatiy holat. Vebda foydalanuvchi odatda barqaror Wi-Fi da; telefonda esa liftda, metroda, qishloqda. Xato holatini ko'rsatmaydigan ilova — "qotib qolgan" ilova: foydalanuvchi bo'sh ekranga qarab, uni yopadi va o'chirib tashlaydi. Bu kod hajmi — real dunyo murakkabligining aksi. Keyingi darsda TanStack Query bu kodning ko'p qismini o'zi bajaradi.
Xulosa
Eslab qoling:
fetchbrauzerdagi kabi;javob.okni doim tekshiring- Uch holat: yuklanmoqda, xato (+ qayta urinish), ma'lumot
AbortController+useEffectcleanup — ekran yopilganda bekor qilish- API qatlami: bazaviy URL, token, xatolar — bitta
api<T>()funksiyada EXPO_PUBLIC_*— muhit o'zgaruvchilari; maxfiy kalitlar ilovada emas- Telefonda
localhost— telefon; kompyuter IP si yoki10.0.2.2 NetInfo— tarmoq holati
Keyingi dars
32-dars: TanStack Query — kesh, qayta yuklash, mutatsiyalar