React useEffect-da Eng Ko'p Uchraydigan 5 Xato va Yechimi

Muallif: Javohir Abdullayev · · React va Frontend

React useEffect-da Eng Ko'p Uchraydigan 5 Xato va Yechimi

useEffect Hooki Nega Ko'pincha Boshog'riq Bo'ladi?

React ekotizimida funksional komponentlarga o'tilgandan buyon useEffect hooki eng ko'p ishlatiladigan, biroq ayni paytda eng ko'p noto'g'ri tushuniladigan vositalardan biriga aylandi. Ko'plab boshlang'ich va hatto tajribali frontend dasturchilar ham uni sinfiy komponentlardagi componentDidMount yoki componentDidUpdate o'rnini bosuvchi oddiy vosita deb bilishadi. Aslida esa useEffect komponent holati (state) bilan tashqi dunyo o'rtasidagi sinxronizatsiya mexanizmidir.

Noto'g'ri yozilgan effektlar ilovangizda cheksiz qayta chizilish (infinite re-render), xotira oqishi (memory leak), kutilmagan ma'lumot almashinuvlari va ilovaning sekinlashuviga sabab bo'ladi. Ushbu maqolada amaliyotda eng ko'p uchraydigan 5 ta xatoni va ularni professional darajada bartaraf etish usullarini batafsil ko'rib chiqamiz.

1-xato: Cheksiz Qayta Chizilish (Infinite Re-render Loop)

Dasturchilar orasida eng mashhur xato: komponent ekranga chiqishi bilan brauzer qotib qoladi yoki konsolda 'Maximum update depth exceeded' xatosi paydo bo'ladi. Bu holat odatda massivga tobelik (dependency array) noto'g'ri berilganda yoki obyekt har gal yangidan yaratilganda yuz beradi.

Xato kod namunasi:

function UserProfile({ userId }) { const [user, setUser] = useState(null); const options = { detailed: true }; useEffect(() => { fetchUser(userId, options).then(data => setUser(data)); }, [options]); }

Muammo shundaki, JavaScript tilida har bir render paytida options nomli yangi obyekt xotirada yaratiladi. Garchi uning ichidagi qiymatlar bir xil bo'lsa-da, xotiradagi manzili yangilanadi. React esa tobelik massividagi o'zgarishni ko'rib, effektni qayta ishga tushiradi. Effekt ichidagi setUser yana re-render chaqiradi va cheksiz zanjir vujudga keladi.

To'g'ri yechim:

function UserProfile({ userId }) { const [user, setUser] = useState(null); useEffect(() => { const options = { detailed: true }; fetchUser(userId, options).then(data => setUser(data)); }, [userId]); }

Obyekt yoki massivlarni komponent tanasida emas, bevosita useEffect ichida e'lon qiling yoki agar obyekt tashqaridan kelsa, useMemo hookidan foydalaning.

2-xato: Qotib Qolgan Holat (Stale Closures)

Boshlang'ich dasturchilar ko'pincha ESLint ogohlantirishlarini e'tiborsiz qoldirib, tobelik massivini bo'sh [] qoldiradilar. Natijada yopilish (closure) mexanizmi sababli effekt ichidagi funksiya o'zgaruvchining faqat ilk qiymatini ko'radi.

Xato kod namunasi:

function Timer() { const [seconds, setSeconds] = useState(0); useEffect(() => { const interval = setInterval(() => { setSeconds(seconds + 1); }, 1000); return () => clearInterval(interval); }, []); return <h1>Vaqt: {seconds}</h1>; }

Bu taymer hech qachon 1 dan oshmaydi! Chunki setInterval ichidagi seconds doimo 0 ga teng bo'lib qoladi.

To'g'ri yechim:

function Timer() { const [seconds, setSeconds] = useState(0); useEffect(() => { const interval = setInterval(() => { setSeconds(prev => prev + 1); }, 1000); return () => clearInterval(interval); }, []); return <h1>Vaqt: {seconds}</h1>; }

Har doim avvalgi holatga tayanuvchi funksional yangilanishdan (prev => prev + 1) foydalaning. Bu tobeliklar ro'yxatini toza saqlash imkonini beradi.

3-xato: Tozalash Funksiyasini (Cleanup) Unutish

Komponent DOM-dan o'chirilganda (unmount) yoki effekt qayta ishga tushishidan oldin tozalash bosqichini yozmaslik jiddiy xotira oqishlariga olib keladi. Bunga event listenerlar, WebSocket ulanishlar yoki taymerlar misol bo'ladi.

To'g'ri yechim:

useEffect(() => { function handleResize() { console.log(window.innerWidth); } window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, []);

Effekt ichida tashqi hodisaga ulandingizmi? Albatta return () => { ... } orqali uni uzib qo'yishni odat qiling.

4-xato: Asinxron Ma'lumot Olishda Race Condition Muammosi

Foydalanuvchi qidiruv maydoniga tez-tez harflar yozganda yoki profillar o'rtasida tez almashganda, serverga bir nechta so'rov ketadi. Tarmoq kechikishi sababli birinchi so'rov oxirgi so'rovdan keyinroq yetib kelishi va noto'g'ri ma'lumot ekranga chiqib qolishi mumkin.

To'g'ri yechim (AbortController bilan):

useEffect(() => { const controller = new AbortController(); async function loadData() { try { const res = await fetch(`/api/user/${userId}`, { signal: controller.signal }); const data = await res.json(); setUser(data); } catch (err) { if (err.name !== 'AbortError') { console.error(err); } } } loadData(); return () => { controller.abort(); }; }, [userId]);

AbortController yordamida parametr o'zgarganda eski so'rov darhol bekor qilinadi va ekranda faqat so'nggi haqiqiy natija aks etadi.

5-xato: Har Qanday Hisob-kitob Uchun useEffect Ishlatish

Ko'pchilik dasturchilar boshqa bir statedan kelib chiqadigan ma'lumotlarni hisoblash uchun ham yangi state ochib, uni useEffect ichida o'zgartiradilar. Bu ortiqcha re-render keltirib chiqaradi va kodni murakkablashtiradi.

Xato usul:

const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); const [fullName, setFullName] = useState(''); useEffect(() => { setFullName(`${firstName} ${lastName}`); }, [firstName, lastName]);

To'g'ri usul:

const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); const fullName = `${firstName} ${lastName}`;

Agar qiymat mavjud props yoki state orqali oddiygina hisoblansa, unga alohida state ham, useEffect ham umuman kerak emas. Agar hisob-kitob juda og'ir bo'lsa, useMemo ishlatish kifoya.

Xulosa

useEffect — qudratli vosita, ammo undan me'yorida va ongli ravishda foydalanish zarur. Har safar effekt yozayotganda quyidagi savollarni o'zingizga bering: bu yerda haqiqatan ham tashqi tizim bilan aloqa bormi, tobeliklar to'liq kiritilganmi va tozalash funksiyasi mavjudmi? Ushbu 5 ta qoidaga amal qilish orqali siz ilovangiz tezligini oshirib, tushunarsiz xatolardan butunlay qutulasiz.

Teglar: #React #React Hooks #useEffect #Frontend #JavaScript