11 β useEffect va yon ta'sirlar¶
β¬ οΈ Oldingi: 10 β Props va kompozitsiya Β· π Kitob boshi Β· Keyingi: 12 β Hooks chuqur β‘οΈ
Bu bobda: komponentdan tashqaridagi dunyo bilan ishlashni o'rganamiz β ma'lumot yuklash, taymerlar, obunalar. Buning vositasi β
useEffecthooki.useEffect(fn, [deps])qachon va necha marta ishlashini, bog'liqliklar massivi (dependency array) nima uchun kerakligini, cleanup (tozalash) bilan taymer/obunani to'g'ri yopishni va eng xavfli xato β cheksiz siklni qanday oldini olishni ko'ramiz. Oxirida API'dan ma'lumot yuklaydigan haqiqiy ekran va jonli soat yozamiz.
Kirish: render hamma narsa emas¶
Oldingi boblarda komponentlarimiz toza edi: state'ni olib, JSX qaytarardi β xolos. Tugma bossangiz state o'zgaradi, ekran qayta chiziladi. Hammasi komponent ichida.
Lekin haqiqiy ilova bunchalik yopiq emas. U tashqi dunyo bilan gaplashishi kerak:
- Internetdan ma'lumot yuklash β serverdan postlar, ob-havo, foydalanuvchi profili.
- Taymer β soat, sanoq, slayd-shou.
- Obuna β klaviatura ochilishi, ilova fonga o'tishi (AppState), qurilma sensorlari.
- Log yozish β analitika, biror voqeani qayd qilish.
Bularning hammasida bitta umumiy narsa bor: ular komponentning asosiy vazifasi (ekranga rasm chizish) emas. Ular β yon ta'sirlar.
Hayotiy o'xshatish. Render β bu rasm chizish kabi: rassom qog'ozga bor kuchini berib rasm chizadi, undan boshqa narsaga chalg'imaydi. Yon ta'sir (side effect) esa β rasm chizib bo'lgandan keyingi ishlar: rasmni ramkalash, devorga osish, do'stga jo'natish. Bular rasmga aloqador, lekin chizish jarayonining o'zi emas. React'da ham: avval ekran chiziladi (render), KEYIN "rasmdan tashqari" ishlar bajariladi (effekt).
Nega bularni to'g'ridan-to'g'ri komponent ichiga yozib bo'lmaydi? Sababi muhim: komponent funksiyasi har render'da boshidan ishlaydi. Agar fetch(...) ni to'g'ridan funksiya ichiga yozsangiz, har qayta-chizishda yangi so'rov ketadi β minglab keraksiz so'rov, sekinlashuv, hatto cheksiz sikl. Yon ta'sirni render'dan ajratish kerak β aynan shu uchun useEffect bor.
1. Yon ta'sir (side effect) nima¶
Yon ta'sir β komponent renderidan tashqaridagi har qanday ish. Ya'ni "JSX hisoblab, qaytarish"dan boshqa narsa:
- Ma'lumot yuklash (
fetch) - Taymer o'rnatish (
setInterval,setTimeout) - Hodisaga obuna bo'lish (
addEventListener, sensor) - Tashqi tizimni o'zgartirish (telefon sarlavhasi, ekran yorug'ligi)
- Konsolga log yozish, analitika yuborish
Render esa toza (pure) bo'lishi kerak: bir xil props/state berilsa, doimo bir xil JSX qaytarishi va boshqa hech narsani "buzmasligi" lozim. Yon ta'sirlar bu tozalikni buzadi β shuning uchun ularni alohida joyga, useEffectga ko'chiramiz.
Eslatma
"Yon ta'sir" qo'rqinchli atama emas. Bu shunchaki "render'dan boshqa, dunyoga ta'sir qiladigan ish" degani. Ma'lumot yuklash ham, soat tiklash ham β yon ta'sir.
2. useEffect β asosiy shakl¶
useEffect β React'ning yon ta'sirlar uchun maxsus hooki. U react paketidan import qilinadi va komponent ichida chaqiriladi:
import { useEffect } from 'react';
useEffect(() => {
// bu yerda yon ta'sir: fetch, taymer, log...
}, [deps]);
useEffect ikkita argument oladi:
- Effekt funksiyasi β
() => {...}β bajariladigan ish. - Bog'liqliklar massivi (
[deps]) β effekt qachon qayta ishlashini boshqaradi (3-bo'limda batafsil).
Eng muhim qoida: effekt render'dan KEYIN ishlaydi. Avval komponent JSX qaytaradi, ekran chiziladi, foydalanuvchi ko'radi β keyin React effektni chaqiradi. Mana shu tartib:
Diagrammada ko'rinib turibdi: (1) komponent render bo'ladi (JSX hisoblanadi) β (2) natija ekranga chiqadi β (3) shundan keyin useEffect ishga tushadi. Effekt hech qachon render'ni "to'xtatib" turmaydi β ekran avval ko'rinadi, ish keyin bajariladi. Shu sabab ilova "muzlab" qolmaydi.
Effektning uch shakli¶
useEffectning ikkinchi argumenti (deps massivi) uch xil bo'lishi mumkin, va har biri butunlay boshqacha xulq beradi:
// 1) Massiv YO'Q β HAR renderda ishlaydi (kam ishlatiladi)
useEffect(() => {
console.log('Har safar render bo\'lganda');
});
// 2) Bo'sh massiv [] β FAQAT BIR MARTA (komponent paydo bo'lganda)
useEffect(() => {
console.log('Faqat bir marta, boshida');
}, []);
// 3) Qiymatli massiv [x] β x O'ZGARGANDA ishlaydi
useEffect(() => {
console.log('soni o\'zgardi:', soni);
}, [soni]);
Bu uch shaklni yaxshilab tushunish β bu bobning eng muhim qismi. Keling, har birini alohida ko'ramiz.
Hayotiy o'xshatish. Bog'liqliklar massivi β bu signalizatsiyaning sozlamasi kabi. "Hech qachon" (massivsiz β har harakatda chiqadi), "faqat eshik birinchi ochilganda" (
[]β bir marta), yoki "faqat ma'lum eshik ochilganda" ([eshik]β o'sha o'zgarganda). Massiv β effektga "qachon uyg'on" deb aytadigan sozlama.
iOS va Android farqi
useEffectning xulqi iOS va Android'da bir xil β bu React darajasidagi mexanizm, platformaga bog'liq emas. Faqat ichidagi ishlar (masalan, AppState fonga o'tish) platformaga xos voqealarga reaksiya qilishi mumkin.
3. Bog'liqliklar massivi (dependency array)¶
Bu β boshlovchilarni eng ko'p chalkashtiradigan tushuncha, shuning uchun sekin-asta boramiz. Bog'liqliklar massivi React'ga shuni aytadi: "effekt ichidagi ish qaysi qiymatlarga bog'liq?" React shu qiymatlarni har render'da tekshiradi: agar birortasi o'zgargan bo'lsa β effektni qayta ishga tushiradi; o'zgarmagan bo'lsa β tinch qoldiradi.
Holat 1: bo'sh massiv [] β bir marta¶
Bu eng ko'p ishlatiladigan shakl. Effekt faqat bir marta, komponent birinchi marta ekranga chiqqanda (buni mount deymiz) ishlaydi va boshqa hech qachon takrorlanmaydi.
useEffect(() => {
console.log('Ekran ochildi β ma\'lumot yuklayman');
// bu yerda fetch(...) β bir martalik yuklash
}, []); // <- bo'sh massiv: faqat boshida
Bu ma'lumot yuklash uchun ideal: ekran ochilganda serverdan ma'lumotni bir marta olib kelasiz.
Holat 2: qiymatli massiv [x] β o'zgarganda¶
Massivga qiymat yozsangiz, effekt o'sha qiymat o'zgarganda qayta ishlaydi:
const [qidiruv, setQidiruv] = useState('');
useEffect(() => {
console.log('Qidiruv o\'zgardi:', qidiruv);
// bu yerda qidiruv bo'yicha yangi so'rov
}, [qidiruv]); // <- qidiruv har o'zgarganda ishlaydi
Foydalanuvchi qidiruv maydoniga yozgan sayin qidiruv o'zgaradi β effekt qayta ishlaydi. Bir nechta qiymatga bog'liq bo'lsa, vergul bilan yozasiz: [qidiruv, filtr].
Holat 3: massiv yo'q β har render'da¶
Agar ikkinchi argumentni umuman bermasangiz, effekt har render'da ishlaydi. Bu juda kam kerak bo'ladi va ko'pincha xato belgisidir β odatda [] yoki [x] kerak.
Massivga nima yozish kerak?¶
Oltin qoida: effekt funksiyasi ichida ishlatadigan har bir o'zgaruvchini (state, prop, yoki tashqi o'zgaruvchi) massivga yozing.
const [id, setId] = useState(1);
const [til, setTil] = useState('uz');
useEffect(() => {
// effekt ichida id VA til ishlatilyapti
yuklash(id, til);
}, [id, til]); // <- ikkalasini ham yozdik
Agar tilni massivga yozishni unutsangiz, til o'zgarganda effekt qayta ishlamaydi β eski til qiymati bilan "qotib" qoladi. Bu eskirgan qiymat (stale value) xatosi.
Maslahat
Bog'liqliklarni o'zingiz hisoblab o'tirmang. Expo loyihasida ESLint o'rnatilgan (eslint-plugin-react-hooks) β u effekt ichidagi qiymatlardan birortasini massivda unutib qoldirsangiz, sariq chiziq bilan ogohlantiradi. Ogohlantirishga quloq soling β u deyarli har doim haq.
Ehtiyot bo'ling
Noto'g'ri bog'liqliklar = bug. Kam yozsangiz β effekt eskirgan qiymat bilan ishlaydi (kerakli paytda yangilanmaydi). State'ni o'zgartiruvchi ishni noto'g'ri massiv bilan yozsangiz β cheksiz sikl (5-bo'limda). Shubha bo'lsa: "effekt ichida nima ishlatdim?" deb so'rab, hammasini yozing.
4. Cleanup β tozalash funksiyasi¶
Ko'p yon ta'sirlar "iz qoldiradi": taymer ishlab turadi, obuna ochiq qoladi. Komponent ekrandan yo'qolganda (buni unmount deymiz) bu izlarni tozalash kerak β aks holda ular fonda ishlayverib, xotira "oqishi" (memory leak) va xatolarga olib keladi.
Buning uchun effekt funksiyasidan boshqa funksiya qaytaramiz β bu cleanup (tozalash) funksiyasi:
useEffect(() => {
const id = setInterval(() => {
console.log('Har soniyada');
}, 1000);
// CLEANUP β qaytariladigan funksiya
return () => {
clearInterval(id); // taymerni to'xtatamiz
};
}, []);
Cleanup ikki holatda chaqiriladi:
- Komponent ekrandan yo'qolganda (unmount).
- Effekt qayta ishlashidan oldin (deps o'zgargan bo'lsa β eski effektni avval tozalab, keyin yangisini boshlaydi).
Diagramma soat misolida ko'rsatadi: komponent paydo bo'lganda setInterval taymer ishga tushadi (har soniyada vaqtni yangilaydi); foydalanuvchi boshqa ekranga o'tib, komponent yo'qolganda cleanup chaqiriladi va clearInterval taymerni to'xtatadi.
Hayotiy o'xshatish. Cleanup β bu mehmonxonadan chiqishdan oldin xonani tartibga keltirish kabi. Kelganingizda chiroqni yoqasiz, konditsionerni ishga tushirasiz (effekt). Chiqayotganda hammasini o'chirib ketasiz (cleanup) β aks holda chiroq behuda yonib turadi, hisob o'sadi. React'da ham: ochgan narsangizni (taymer, obuna) yopib keting.
Qoida
Agar effekt biror narsani ochsa (taymer, obuna, listener) β cleanup'da uni yoping. setInterval β clearInterval, setTimeout β clearTimeout, addEventListener/addEventListener β remove(). "Nimani ochdim β shuni yopaman."
5. Cheksiz sikl tuzog'i (KRITIK xato)¶
Bu β useEffect bilan bog'liq eng xavfli xato, va deyarli har bir boshlovchi unga bir marta tushadi. Keling, mexanizmni tushunaylik, toki siz tushmang.
Sikl mana shunday hosil bo'ladi:
- Effekt ishlaydi va state'ni o'zgartiradi (
setSoni). - State o'zgargani uchun komponent qayta render bo'ladi.
- Effekt o'sha state'ga bog'liq (massivda bor), shuning uchun u yana ishlaydi.
- U yana state'ni o'zgartiradi β yana render β yana effekt β ... cheksiz.
Mana xato kod (buni ishlatmang):
function Yomon() {
const [soni, setSoni] = useState(0);
useEffect(() => {
setSoni(soni + 1); // β deps'da soni bor, ichida soni'ni o'zgartiramiz
}, [soni]); // β -> render -> effekt -> render -> ... CHEKSIZ!
return <Text>{soni}</Text>;
}
soni o'zgaradi β render β effekt ishlaydi β soni yana o'zgaradi β render β ... Ilova qotib qoladi yoki "Maximum update depth exceeded" xatosini beradi.
Ehtiyot bo'ling
Cheksiz sikl belgisi: effekt ichida setX(...) chaqiryapsiz va x o'sha effektning bog'liqliklar massivida bor. Bu deyarli har doim sikl yaratadi.
Qanday oldini olish kerak?
- Yangilashni shartga o'rang. State'ni faqat kerak bo'lganda o'zgartiring (masalan, serverdan kelgan ma'lumot avvalgisidan farq qilsagina).
- Funksional yangilashdan foydalaning.
setSoni((avvalgi) => avvalgi + 1)ishlatsangiz,sonini o'qishingiz shart emas β uni massivdan olib tashlay olasiz. (Lekin agar maqsadingiz "bir marta oshirish" bo'lsa, baribir[]ishlating, taymer ichida emas.) - State o'rniga to'g'ri joyni tanlang. Ko'pincha effekt ichida state yangilash umuman kerak emas β buni hodisa ishlovchisiga (
onPress) ko'chiring, yoki render paytida hisoblang.
Masalan, "bir marta sanog'ni 10 ga o'rnatish" kerak bo'lsa:
useEffect(() => {
setSoni(10); // β bir marta, deps bo'sh -> sikl yo'q
}, []); // soni massivda YO'Q
6. Amaliy effektlar¶
Nazariyani ko'rdik β endi haqiqiy vazifalarda qo'llaymiz.
Ma'lumot yuklash ([])¶
Eng keng tarqalgan foydalanish: ekran ochilganda serverdan ma'lumot olib kelish. fetch ishlatamiz (async funksiya effekt ichida e'lon qilinadi β effektning o'zini async qilib bo'lmaydi):
useEffect(() => {
async function yukla() {
const javob = await fetch('https://jsonplaceholder.typicode.com/posts');
const malumot = await javob.json();
setPostlar(malumot);
}
yukla();
}, []); // bir marta yuklaymiz
Nega effektni o'zini async qilmaymiz?
useEffect(async () => {...}) noto'g'ri β async funksiya Promise qaytaradi, lekin React effektdan cleanup funksiyasi kutadi. Shuning uchun ichkarida alohida async funksiya yozib (yukla), uni darrov chaqiramiz.
Taymer / soat (cleanup bilan)¶
Har soniyada yangilanadigan soat β setInterval + albatta clearInterval:
const [vaqt, setVaqt] = useState(new Date());
useEffect(() => {
const id = setInterval(() => setVaqt(new Date()), 1000);
return () => clearInterval(id); // tozalash MAJBURIY
}, []);
Qidiruvda debounce ([search])¶
Foydalanuvchi har harf yozganda darrov so'rov yubormaslik uchun β biroz kutamiz (debounce). setTimeout + cleanup'da clearTimeout ajoyib ishlaydi: har yangi harf eski taymerni bekor qiladi, faqat foydalanuvchi to'xtaganda so'rov ketadi.
const [qidiruv, setQidiruv] = useState('');
useEffect(() => {
if (qidiruv === '') return; // bo'sh bo'lsa qidirmaymiz
const id = setTimeout(() => {
console.log('Qidiruv so\'rovi:', qidiruv); // bu yerda fetch
}, 500); // 500ms kutamiz
return () => clearTimeout(id); // har harfda eski taymerni bekor qil
}, [qidiruv]); // qidiruv o'zgarganda
Bu naqsh juda nafis: foydalanuvchi "react native" deb tez yozsa, har harfda taymer qayta-qayta bekor bo'ladi va faqat oxirgi (yozish to'xtagan) holatda 500ms o'tib so'rov ketadi. Server behuda yuklanmaydi.
Klaviatura / AppState obunasi¶
Tashqi voqealarga obuna β masalan, ilova fonga (background) yoki faol (active) holatga o'tganini kuzatish. AppState react-native dan keladi:
import { AppState } from 'react-native';
useEffect(() => {
const obuna = AppState.addEventListener('change', (yangiHolat) => {
console.log('Ilova holati:', yangiHolat); // 'active' | 'background' | 'inactive'
});
return () => obuna.remove(); // obunani tozalash
}, []);
E'tibor bering: bu yerda ham obuna ochildi β cleanup'da yopildi qoidasi ishlaydi. AppState.addEventListener obyekt qaytaradi, uning .remove() metodi obunani bekor qiladi.
7. useEffect mobil kontekstda¶
Mobil ilovada useEffectni tushunish ayniqsa muhim, chunki ekranlar tez-tez ochilib-yopiladi va ilova fonga o'tib turadi.
AppState β fon/faol holat¶
Yuqorida ko'rganimizdek, AppState ilovaning 'active' (ekranda), 'background' (boshqa ilovaga o'tildi) yoki 'inactive' (oraliq) holatda ekanini bildiradi. Masalan, ilova fonga o'tganda taymerni to'xtatib, qaytganda davom ettirishingiz mumkin.
useFocusEffect β ekran fokusda¶
Expo Router'da bitta nozik nuqta bor: tab'lar yoki stack'da ekran butunlay yo'qolmasligi mumkin β u shunchaki fonda turadi (siz boshqa tab'dasiz). Oddiy useEffect(() => {...}, []) faqat ekran birinchi yaratilganda ishlaydi, har safar qaytib kelganingizda emas.
Agar siz har safar ekranga qaytganda biror ish bajarmoqchi bo'lsangiz (masalan, ma'lumotni yangilash), expo-router dan useFocusEffect ishlatasiz:
import { useFocusEffect } from 'expo-router';
import { useCallback } from 'react';
useFocusEffect(
useCallback(() => {
console.log('Ekran fokusga keldi');
return () => console.log('Ekran fokusdan ketdi'); // cleanup ham bor
}, [])
);
Eslatma
useFocusEffectni hozircha faqat eslatib o'tyapmiz β uni navigatsiya boblarida (14β16-bob) batafsil ko'ramiz. Asosiy g'oya: useEffect "komponent yaratildi/yo'qoldi" ga, useFocusEffect esa "ekran ko'rinadi/yashirinadi" ga reaksiya qiladi. Boshlanishida useEffect yetarli.
8. React 19 va React Compiler (qisqa eslatma)¶
Bu kitob React 19 va Expo SDK 56 ga asoslangan, ularda React Compiler (eksperimental) bor. React Compiler ba'zi optimizatsiyalarni avtomatik qiladi β masalan, qaysi qiymatlarni eslab qolish (memoizatsiya) kerakligini o'zi aniqlaydi (useMemo/useCallback ko'pincha kerak bo'lmay qoladi β bu haqda 12-bobda).
Lekin muhim: React Compiler useEffectni o'rnini bosmaydi. Yon ta'sirlar (ma'lumot yuklash, taymer, obuna) baribir useEffectda bo'ladi. Kompilyator faqat tezlikni yaxshilaydi, yon ta'sir mantig'ini siz baribir to'g'ri yozishingiz, deps va cleanup'ni o'zingiz boshqarishingiz kerak.
Maslahat
Zamonaviy React'da tendensiya shu: ma'lumot yuklashni useEffectda qo'lda yozish o'rniga, ko'pincha TanStack Query (React Query) kabi kutubxonalardan foydalaniladi β ular loading/error/cache'ni o'zi boshqaradi. Lekin uning ostida ham useEffect mantig'i yotadi, shuning uchun avval useEffectni puxta tushunish shart. Bu kutubxonalarni keyingi boblarda eslatamiz.
9. To'liq misol β API'dan ma'lumot yuklaydigan ekran¶
Endi hamma narsani birlashtiramiz: bobdagi eng muhim amaliy naqsh β ma'lumot yuklash ekrani loading/data/error holatlari va cleanup (AbortController) bilan. Quyidagi kod jonli Expo loyihada npx tsc --noEmit bilan tekshirilgan.
// app/postlar.tsx β API'dan postlar yuklaydigan ekran
import { View, Text, FlatList, StyleSheet, ActivityIndicator } from 'react-native';
import { useState, useEffect } from 'react';
type Post = { id: number; title: string };
export default function Postlar() {
const [postlar, setPostlar] = useState<Post[]>([]);
const [yuklanmoqda, setYuklanmoqda] = useState(true);
const [xato, setXato] = useState<string | null>(null);
useEffect(() => {
// AbortController β yarim yo'lda so'rovni bekor qilish vositasi
const controller = new AbortController();
async function yukla() {
try {
setYuklanmoqda(true);
setXato(null);
const javob = await fetch(
'https://jsonplaceholder.typicode.com/posts?_limit=10',
{ signal: controller.signal } // bekor qilish signalini ulaymiz
);
if (!javob.ok) throw new Error('Server xatosi: ' + javob.status);
const malumot: Post[] = await javob.json();
setPostlar(malumot);
} catch (e) {
// ekran yopilib so'rov bekor qilingan bo'lsa β bu xato emas
if (e instanceof Error && e.name === 'AbortError') return;
setXato(e instanceof Error ? e.message : 'Noma\'lum xato');
} finally {
setYuklanmoqda(false);
}
}
yukla();
// CLEANUP: ekran yopilsa, tugamagan so'rovni bekor qilamiz
return () => controller.abort();
}, []); // bir marta yuklaymiz
// Uch holat: yuklanmoqda / xato / ma'lumot
if (yuklanmoqda) {
return (
<View style={styles.markaz}>
<ActivityIndicator size="large" color="#0ea5e9" />
<Text style={styles.holatMatn}>Yuklanmoqda...</Text>
</View>
);
}
if (xato) {
return (
<View style={styles.markaz}>
<Text style={styles.xato}>Xato: {xato}</Text>
</View>
);
}
return (
<FlatList
data={postlar}
keyExtractor={(item) => item.id.toString()}
contentContainerStyle={styles.royxat}
renderItem={({ item }) => (
<View style={styles.karta}>
<Text style={styles.sarlavha}>{item.title}</Text>
</View>
)}
/>
);
}
const styles = StyleSheet.create({
markaz: { flex: 1, alignItems: 'center', justifyContent: 'center', gap: 12, backgroundColor: '#f8fafc' },
holatMatn: { fontSize: 14, color: '#475569' },
xato: { fontSize: 15, color: '#dc2626', textAlign: 'center', paddingHorizontal: 24 },
royxat: { padding: 16, gap: 10 },
karta: {
backgroundColor: '#ffffff', padding: 16, borderRadius: 12,
borderWidth: 1, borderColor: '#bae6fd',
},
sarlavha: { fontSize: 15, color: '#1e293b', fontWeight: '600' },
});
Bu ekranda bobning barcha tushunchalari bor:
useEffect(..., [])β ma'lumot bir marta, ekran ochilganda yuklanadi.- Uch holat β
yuklanmoqda(spinner),xato(qizil matn),postlar(ro'yxat). Boshlovchilar ko'pincha faqat ma'lumotni o'ylaydi, lekin yuklanish va xato holatlari ham shart. asyncichkarida β effekt o'ziasyncemas, ichidayukla()funksiyasi.- Cleanup +
AbortControllerβ ekran yopilsa, tugamagan so'rov bekor qilinadi, "yo'q komponentni yangilash" ogohlantirishi chiqmaydi.
Muqobil: jonli soat¶
Soddaroq, lekin cleanup'ni yorqin ko'rsatadigan misol β har soniyada yangilanadigan soat. Bu ham tsc bilan tekshirilgan:
// app/soat.tsx β jonli raqamli soat
import { View, Text, StyleSheet } from 'react-native';
import { useState, useEffect } from 'react';
export default function Soat() {
const [vaqt, setVaqt] = useState(new Date());
useEffect(() => {
// har soniyada vaqtni yangilaydigan taymer
const id = setInterval(() => setVaqt(new Date()), 1000);
// CLEANUP: komponent yo'qolganda taymerni to'xtatamiz
return () => clearInterval(id);
}, []); // taymer bir marta o'rnatiladi
return (
<View style={styles.box}>
<Text style={styles.soat}>{vaqt.toLocaleTimeString()}</Text>
<Text style={styles.sana}>{vaqt.toLocaleDateString()}</Text>
</View>
);
}
const styles = StyleSheet.create({
box: { flex: 1, alignItems: 'center', justifyContent: 'center', gap: 8, backgroundColor: '#f8fafc' },
soat: { fontSize: 48, fontWeight: '800', color: '#1e293b', fontVariant: ['tabular-nums'] },
sana: { fontSize: 16, color: '#475569' },
});
Bu yerda clearIntervalni unutsangiz, foydalanuvchi boshqa ekranga o'tgach ham taymer fonda har soniya setVaqt chaqirib turadi β yo'q komponentni yangilashga urinib, xotira oqishi va ogohlantirishlarga sabab bo'ladi. Cleanup buni hal qiladi.
Tekshirib ko'ring
Soat misolini loyihangizga tering (npx expo start). So'ng return () => clearInterval(id) qatorini vaqtincha o'chiring va terminaldagi ogohlantirishlarni kuzating (yoki ekranlar orasida tez-tez yuring). Cleanup'siz nima bo'lishini his qilgach, qatorni qaytaring.
Xulosa¶
- Yon ta'sir (side effect) β render'dan tashqaridagi ish: ma'lumot yuklash, taymer, obuna, log. Render "rasm chizish", effekt "rasmdan keyingi ishlar".
useEffect(fn, [deps])effektni render'dan ajratadi va uni render'dan KEYIN (ekran chizilgach) ishga tushiradi.- Uch shakl: massivsiz β har render (kam kerak);
[]β faqat bir marta (mount, ma'lumot yuklash);[x]βxo'zgarganda. - Bog'liqliklar massivi: effekt ichida ishlatilgan har state/prop'ni yozing. Kam yozsangiz β eskirgan qiymat bug'i. ESLint
react-hooksqoidasi yordam beradi. - Cleanup β effektdan
return () => {...}qaytariladi; komponent yo'qolganda yoki effekt qayta ishlashidan oldin chaqiriladi. "Nimani ochding β shuni yop":setIntervalβclearInterval, obunaβ.remove(). - Cheksiz sikl β effekt ichida deps'dagi state'ni yangilash β render β effekt β ... cheksiz. Funksional yangilash, shart, yoki to'g'ri joyni tanlash bilan oldini oling.
- Ma'lumot yuklash uchun loading/error/data uch holatini va
AbortControllercleanup'ini ishlating. Effektniasyncqilmang β ichidaasyncfunksiya yozing. - Mobil kontekst:
AppState(fon/faol),useFocusEffect(ekran fokusda β Expo Router). React 19/Compiler optimizatsiyani avtomatlashtiradi, lekinuseEffecttushunish baribir shart.
Amaliy mashqlar¶
-
Salom-log (oson). Ekran ochilganda konsolga "Ekran ochildi" deb bir marta yozadigan
useEffectyozing. So'ng massivni[]dan olib tashlab, har render'da chiqishini kuzating (ekranda tugma qo'yib, state'ni o'zgartiring). Farqni his qiling. -
Jonli soat cleanup bilan (oson). Yuqoridagi
Soatkomponentini o'zingiz qaytadan yozing.setIntervalbilan har soniyada vaqtni yangilang vareturn () => clearInterval(id)bilan tozalang. Cleanup'ni vaqtincha o'chirib, ogohlantirishni ko'ring. -
Deps o'zgarishini kuzatish (o'rta).
useStatebilansonisaqlang va uni oshiradigan tugma qo'ying.useEffect(() => { console.log('soni:', soni) }, [soni])yozing. Tugmani bosib, har o'zgarishda log chiqishini ko'ring. So'ng massivni[]ga o'zgartirib, endi faqat bir marta chiqishini taqqoslang. -
Debounce qidiruv (o'rta).
TextInputqo'ying (value/onChangeTextβ 06-bobdan). Foydalanuvchi yozganda darrov emas, 500ms kutib "Qidirilmoqda: ..." matnini ko'rsating.setTimeout+ cleanup'daclearTimeoutishlating, deps =[qidiruv]. Tez yozganda faqat oxirida ishlashini ko'ring. -
API ekrani to'liq (qiyin).
https://jsonplaceholder.typicode.com/usersdan foydalanuvchilarni yuklang.yuklanmoqda(ActivityIndicator),xato(qizil matn) vadata(FlatListbilan ism/email) uch holatini to'liq qayta ishlang.AbortControllercleanup'ini qo'shing. Qo'shimcha: "Qayta yuklash" tugmasi bosilganda effektni qayta ishga tushiradigan[hisoblagich]deps qo'shing.
β¬ οΈ Oldingi: 10 β Props va kompozitsiya Β· π Kitob boshi Β· Keyingi: 12 β Hooks chuqur β‘οΈ