WisarWisar
Hamroh materiallar/Intervyu41 daqiqa

Texnik intervyu: React (+ Next.js asoslari)

Bu fayl — full-stack dasturchi uchun React bo'yicha chuqur intervyu tayyorgarligi. Har bir savol real suhbatlardan olingan: klassik nazariy savollardan tortib, tajribali muhandisni ajratib beradigan tuzoq (gotcha) savollargacha.

Qanday foydalanish

  • Avval savolni o'qing, javobni ovoz chiqarib ayting, keyin tekshiring — intervyu bu bilimni gapirib bera olish.
  • Har javob to'rt qavatdan iborat: Ta'rif Mexanizm (ichki, nega/qanday) Kod Xato Follow-up.
  • Belgilar: Junior · Middle · Senior.
  • Kodni yodlamang — modelni tushuning. Intervyuer har doim "nega?" deb so'raydi.

React savollarining 80% i bitta narsaga borib taqaladi: "Komponent qachon va nega qayta render (re-render) bo'ladi?" Shu savolga har tomondan javob bera olsangiz — yarim ishni bajardingiz.


1-BO'LIM. Asoslar va ichki mexanizm

S: React nima va u qanday muammoni yechadi? (Junior)

J: Ta'rif. React — foydalanuvchi interfeysini (UI) qurish uchun deklarativ, komponentga asoslangan JavaScript kutubxonasi (framework emas, aynan library). Facebook (hozir Meta) tomonidan yaratilgan.

Mexanizm. Asosiy g'oya: UI = f(state). Ya'ni interfeys — bu holatning (state) funksiyasi. Siz DOM'ni qo'lda o'zgartirmaysiz (imperativ document.getElementById(...).innerHTML = ... yo'q); siz shunchaki "shu holatda ekran shunday ko'rinishi kerak" deb e'lon qilasiz (deklarativ), React esa haqiqiy DOM'ni shu holatga keltirish uchun kerakli minimal o'zgarishlarni o'zi hisoblaydi. Bu jarayon reconciliation deyiladi.

Kod misol.

jsx
// Imperativ (vanilla JS) — "qanday" qilishni yozamiz
const btn = document.querySelector('#btn');
let count = 0;
btn.addEventListener('click', () => {
  count++;
  document.querySelector('#label').textContent = `Bosildi: ${count}`;
});

// Deklarativ (React) — "nima" ko'rinishini yozamiz
function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>Bosildi: {count}</button>;
}

Keng tarqalgan xato. React'ni "framework" deb atash. React faqat UI qatlamini beradi; routing, data-fetching, build kabilar alohida kutubxonalar (React Router, TanStack Query) yoki meta-framework (Next.js) orqali qo'shiladi.

Follow-up. "React library bo'lsa, Next.js nima?" Next.js — React ustiga qurilgan meta-framework: routing, SSR/SSG, bundling, server komponentlarni tayyor beradi.


S: Virtual DOM nima va u qanday ishlaydi? (Middle)

J: Ta'rif. Virtual DOM (VDOM) — haqiqiy DOM'ning yengil, xotiradagi JavaScript obyekt ko'rinishidagi nusxasi. Har bir element { type, props, children } ko'rinishidagi oddiy obyekt.

Mexanizm. Haqiqiy DOM operatsiyalari qimmat (layout, reflow, repaint). React har render'da:

  1. Yangi VDOM daraxtini quradi (bu arzon — oddiy obyektlar).
  2. Uni oldingi VDOM bilan solishtiradi (diffing).
  3. Faqat farqni aniqlaydi va haqiqiy DOM'ga eng kam o'zgarishni qo'llaydi (batching bilan).

Ya'ni VDOM o'zi tezlik uchun emas — u imperativ DOM boshqaruvini deklarativ modelga aylantirish uchun. "Tez" bo'lishi — ortiqcha DOM operatsiyalarini oldini olgani uchun.

Kod misol.

jsx
// JSX shunday obyektga aylanadi (soddalashtirilgan):
const element = <h1 className="title">Salom</h1>;
// ≈
const element = {
  type: 'h1',
  props: { className: 'title', children: 'Salom' },
};

Keng tarqalgan xato. "Virtual DOM har doim tez" degan mif. Aslida ba'zan qo'lda yozilgan aniq DOM operatsiyasi tezroq. VDOM'ning yutug'i — tezlikda emas, soddalik va bashoratlilikda (predictability).

Follow-up. "VDOM diffing algoritmi O(n³) bo'lishi mumkin edi, React uni qanday O(n) ga tushirgan?" Ikki evristika bilan: (1) turli tipdagi elementlar butunlay almashtiriladi, (2) key orqali ro'yxat elementlari aniqlanadi.


S: Reconciliation va diffing algoritmi ichkarida qanday ishlaydi? (Senior)

J: Ta'rif. Reconciliation — React yangi VDOM daraxtini eski bilan solishtirib, haqiqiy DOM'ni yangilash uchun nima o'zgarganini aniqlash jarayoni. Diffing — shu solishtirishning o'zi.

Mexanizm (chuqur). Umumiy daraxt-solishtirish O(n³). React uni ikkita amaliy taxminga tayanib O(n) ga tushiradi:

  1. Turli element tiplari — turli daraxtlar. Agar element tipi o'zgarsa (<div> <span>, yoki <Counter> <Profile>), React eski daraxtchani butunlay yo'q qiladi (unmount, state yo'qoladi) va yangisini noldan quradi. Ostidagi bolalarni umuman solishtirmaydi.

  2. Bir xil tip — atributlarni yangilaydi. Element tipi bir xil bo'lsa (<div className="a"> <div className="b">), React DOM nodini saqlaydi, faqat o'zgargan atributni yangilaydi, keyin bolalariga rekursiv kiradi.

  3. Bolalar ro'yxati — key orqali. Ro'yxatdagi elementlarni pozitsiya bo'yicha emas, key bo'yicha moslashtiradi. key barqaror identifikatorni beradi, shuning uchun element o'rin almashsa ham React uni "o'sha element" deb tanaydi.

Kod misol.

jsx
// Tip o'zgardi  to'liq almashtirish (state yo'qoladi):
{isEditing ? <Input /> : <Text />}   // InputText har safar unmount/mount

// Tip bir xil  holat saqlanadi, faqat prop yangilanadi:
<Message color={isError ? 'red' : 'green'} text={msg} />

Keng tarqalgan xato. Shartli renderda bir xil tipdagi komponentni turli joyda joylashtirish state'ni kutilmaganda saqlab qolishga olib keladi. Masalan {cond ? <Panel a/> : <Panel b/>} — ikkalasi ham <Panel> bo'lgani uchun React uni bir xil instansiya deb hisoblaydi va ichki state saqlanadi.

Follow-up. "Ikki komponentni turli instansiya sifatida majburan ajratish uchun nima qilasiz?" Ularga har xil key berish (key-ni faqat ro'yxatlarda emas, "state'ni resetlash" vositasi sifatida ham ishlatish mumkin).


S: React Fiber nima va u nima uchun kerak bo'lgan? (Senior)

J: Ta'rif. Fiber — React 16'dan boshlab kelgan reconciliation dvigatelining yangi arxitekturasi. Har bir Fiber — bu komponent/DOM tuguni haqidagi ma'lumotni saqlaydigan ish birligi (unit of work) — oddiy obyekt.

Mexanizm. Eski (Stack) reconciler render'ni rekursiv va uzilmas bajarardi: katta daraxt render bo'lganda main thread bloklanib, animatsiya va inputlar sekinlashardi. Fiber render ishini kichik bo'laklarga bo'ladi va ularni to'xtatib-davom ettirish (interruptible), ustuvorlik berish, hatto bekor qilish imkonini beradi. Bu concurrent rendering (React 18) ning poydevori.

Fiber ikki fazada ishlaydi:

  • Render/reconcile fazasi — asinxron, uzilishi mumkin, DOM'ga tegmaydi (VDOM'ni tayyorlaydi).
  • Commit fazasi — sinxron, uzilmaydi, DOM'ni bir zumda yangilaydi.

Kod misol.

jsx
// Fiber concurrent imkoniyati amalda — useTransition:
const [isPending, startTransition] = useTransition();

function onChange(e) {
  setQuery(e.target.value);              // shoshilinch (urgent) yangilanish
  startTransition(() => {
    setResults(filter(e.target.value));  // ustuvorligi past — uzilishi mumkin
  });
}

Keng tarqalgan xato. Fiber'ni "yangi Virtual DOM" deb tushunish. Fiber — VDOM'ni qanday qayta ishlash (planlashtirish) mexanizmi, VDOM'ning o'zi emas.

Follow-up. "Nega StrictMode'da effektlar ikki marta ishlaydi?" Concurrent modelda komponent mount/unmount qayta bo'lishiga chidamli bo'lishi kerak; StrictMode buni development'da simulyatsiya qiladi.


S: JSX nima va u qanday ishlaydi? (Middle)

J: Ta'rif. JSX — JavaScript'ning sintaktik kengaytmasi (syntactic sugar): HTML'ga o'xshash yozuvni JS ichida yozish imkonini beradi. Brauzer JSX'ni tushunmaydi — u build vaqtida (Babel/SWC) oddiy JS chaqiruvlariga aylantiriladi.

Mexanizm. Har bir JSX teg React.createElement(type, props, ...children) chaqiruviga (React 17+ da jsx() runtime funksiyasiga) aylanadi, u esa yuqorida ko'rgan VDOM obyektini qaytaradi. Shuning uchun JSX aslida "shablon" emas — bu oddiy JS ifoda (expression), uni o'zgaruvchiga berish, funksiyadan qaytarish mumkin.

Kod misol.

jsx
const el = <h1 id="t">Salom, {name}</h1>;

// Babel buni shunday aylantiradi:
const el = React.createElement('h1', { id: 't' }, 'Salom, ', name);

Keng tarqalgan xato. JSX ichida if yoki for statement yozishga urinish. JSX faqat ifoda (expression) qabul qiladi — shuning uchun ternar (? :), &&, .map() ishlatiladi, if esa {} ichida emas, tashqarida yoziladi.

Follow-up. "Nega har bir faylda import React kerak edi, endi esa yo'q?" React 17'gacha JSX React.createElement ga aylanardi (React kerak edi); yangi JSX transform avtomatik react/jsx-runtime dan import qiladi.


S: key prop nima uchun kerak va nega index'ni key qilib ishlatish yomon? (Middle)

J: Ta'rif. key — ro'yxatdagi (.map() bilan chizilgan) har bir elementning barqaror, noyob identifikatori. React uni reconciliation'da elementlarni moslashtirish uchun ishlatadi.

Mexanizm. Ro'yxat o'zgarganda (element qo'shildi/o'chdi/o'rin almashdi), React eski va yangi bolalarni key bo'yicha solishtiradi. key yordamida u "bu — o'sha element, faqat joyi o'zgardi" deb tushunadi va DOM nodini (hamda ichki state'ni, input fokusini) qayta ishlatadi, o'chirib-yaratmaydi.

index'ni key qilsangiz — ro'yxat boshiga element qo'shilganda barcha indekslar suriladi. React key=0 ni "o'sha element" deb o'ylaydi, lekin unda endi boshqa ma'lumot bor state va DOM noto'g'ri elementga "yopishib" qoladi.

Kod misol.

jsx
//  Yomon — ro'yxat o'zgarsa, input qiymatlari aralashadi:
{items.map((item, i) => <TodoRow key={i} item={item} />)}

//  To'g'ri — barqaror ID:
{items.map((item) => <TodoRow key={item.id} item={item} />)}

Keng tarqalgan xato. key'ni oddiy "React ogohlantirishini o'chirish" deb qarash. Ro'yxat statik va hech qachon tartibi o'zgarmasa index zararsiz, lekin qo'shish/o'chirish/saralash bo'lsa — kraxlab beruvchi buglar (noto'g'ri fokus, aralashgan checkbox'lar) chiqadi.

Follow-up. "key'ni tashqi <div>ga qo'yish uchun <Fragment> ni to'liq yozish kerak. Nega qisqa <>...</> sintaksisi key qabul qilmaydi?" Qisqa sintaksis prop qabul qilolmaydi; key kerak bo'lsa <React.Fragment key={...}> yoziladi.


2-BO'LIM. Props va State

S: Props va state farqi nima? (Junior)

J: Ta'rif. Props — komponentga tashqaridan (ota-komponentdan) uzatiladigan, faqat o'qish uchun (read-only) ma'lumot. State — komponentning ichki, vaqt bilan o'zgaradigan xususiy ma'lumoti.

Mexanizm. Props bir yo'nalishli oqim (one-way data flow) bo'yicha yuqoridan pastga oqadi — bola uni o'zgartira olmaydi. State esa useState/useReducer orqali komponent ichida saqlanadi; uni yangilash (setState) re-render'ni ishga tushiradi. React'da ma'lumot doim yuqoridan pastga oqadi; state'ni yuqoriga ko'tarish kerak bo'lsa — lifting state up.

Kod misol.

jsx
function Parent() {
  const [count, setCount] = useState(0);   // state — bu yerda "egasi"
  return <Child count={count} onInc={() => setCount(c => c + 1)} />;
}
function Child({ count, onInc }) {          // props — faqat o'qiydi
  return <button onClick={onInc}>{count}</button>;
}

Keng tarqalgan xato. Props'ni mutatsiya qilishga urinish (props.x = 5). Bu taqiqlangan — props immutable. O'zgartirish kerak bo'lsa, state'ni otada saqlab, callback orqali yangilanadi.

Follow-up. "Bir prop'ni to'g'ridan-to'g'ri state boshlang'ich qiymati qilsak, keyin prop o'zgarsa state yangilanadimi?" Yo'q. useState(props.x) faqat birinchi render'da o'qiladi; keyin prop o'zgarsa state avtomatik yangilanmaydi (bu klassik tuzoq).


S: useState yangilanishi nega asinxron ko'rinadi? (Middle)

J: Ta'rif. setState chaqirilganda state darhol o'zgarmaydi — React yangilanishni navbatga qo'yadi (batch) va keyingi render'da yangi qiymatni beradi.

Mexanizm. state o'zgaruvchisi — joriy render uchun muzlatilgan (snapshot) qiymat. setState(x) React'ga "keyingi render shu qiymat bilan bo'lsin" deydi, lekin joriy funksiya ichida state hali eski qiymatda qoladi (closure). React bir hodisa (event) ichidagi bir nechta setState'ni birlashtirib (batching), bitta re-render qiladi — samaradorlik uchun.

Kod misol.

jsx
const [count, setCount] = useState(0);

function handleClick() {
  setCount(count + 1);   // count = 0  1 rejalashtiriladi
  setCount(count + 1);   // count HALI 0  yana 1 (2 emas!)
  console.log(count);    // 0 — eski snapshot

  //  To'g'risi — updater funksiya (avvalgi qiymatga tayanadi):
  setCount(c => c + 1);  // 0  1
  setCount(c => c + 1);  // 1  2
}

Keng tarqalgan xato. setCount(count + 1) ni ketma-ket chaqirib "2 marta oshdi" deb kutish. Har ikkalasi ham bir xil eski count snapshot'iga tayanadi. Avvalgi qiymatga tayanish kerak bo'lsa — updater funksiya setCount(c => c + 1).

Follow-up. "React 18'gacha setState faqat React hodisalarida batch bo'lardi, setTimeout ichida yo'q. 18'da nima o'zgardi?" React 18 avtomatik batchingni hamma joyga (Promise, setTimeout, native handler) yoyildi.


S: Controlled va uncontrolled komponent farqi nima? (Middle)

J: Ta'rif. Controlled — form elementining qiymati React stateda saqlanadi (React "yagona haqiqat manbai"). Uncontrolled — qiymat DOM'ning o'zida saqlanadi, React unga ref orqali kerak bo'lganda murojaat qiladi.

Mexanizm. Controlled'da value={state} va onChange bir-biriga bog'langan: har bosishda state yangilanadi re-render input yangi qiymatni ko'rsatadi. Bu React'ga har harfda validatsiya, formatlash, tugmani o'chirish imkonini beradi. Uncontrolled'da bu tsikl yo'q — brauzer inputni o'zi boshqaradi, siz faqat kerak paytda ref.current.value ni o'qiysiz.

Kod misol.

jsx
// Controlled:
const [name, setName] = useState('');
<input value={name} onChange={e => setName(e.target.value)} />

// Uncontrolled:
const inputRef = useRef(null);
<input ref={inputRef} defaultValue="" />
// keyin: inputRef.current.value

Keng tarqalgan xato. value={undefined} berib keyin string berish — React inputni uncontrolled'dan controlled'ga o'tkazganini ogohlantiradi. Har doim value={name ?? ''} bilan boshlang'ich qiymatni ta'minlang.

Follow-up. "Katta formada har harfga re-render bo'lsa sekinlashadi. Nima qilasiz?" Uncontrolled + ref yoki React Hook Form (u ichkarida uncontrolled ishlatib re-render'ni minimallashtiradi).


3-BO'LIM. Hooks

S: Hook nima va hooklarning qoidalari (Rules of Hooks) qanday? (Junior)

J: Ta'rif. Hook — funksional komponentga state va React imkoniyatlarini (lifecycle, context) "ulash" imkonini beruvchi funksiya (use bilan boshlanadi). 2 ta qat'iy qoida bor:

  1. Hook'ni faqat eng yuqori darajada chaqiring — sikl, shart (if), ich-ichki funksiya ichida emas.
  2. Hook'ni faqat React funksiyalarida (komponent yoki boshqa hook) chaqiring.

Mexanizm (nega). React hooklarni nom bo'yicha emas, chaqirilish tartibi (order) bo'yicha xotirada saqlaydi — ichkarida bu bog'langan ro'yxat (linked list). Birinchi render'da useState, useEffect... tartib bilan yoziladi. Agar keyingi render'da shart tufayli bittasi o'tkazib yuborilsa, tartib suriladi va React state'ni noto'g'ri hook'ga bog'laydi — hamma narsa buziladi.

Kod misol.

jsx
//  Shart ichida hook — tartib buziladi:
if (isLoggedIn) {
  const [name, setName] = useState('');  // XATO
}

//  Shart hook ichida, hook doim chaqiriladi:
const [name, setName] = useState('');
if (isLoggedIn) { /* name'dan foydalan */ }

Keng tarqalgan xato. Erta return dan keyin hook chaqirish. if (!user) return null; dan pastda useEffect bo'lsa — ba'zi render'larda u chaqirilmaydi tartib buziladi.

Follow-up. "React qanday qilib bir komponentda 5 ta useState'ni bir-biridan ajratadi, axir ular bir xil funksiya?" Chaqirilish tartibi va Fiber tugunidagi hook ro'yxatidagi pozitsiya orqali.


S: useEffect qanday ishlaydi: lifecycle, cleanup, dependency array? (Middle)

J: Ta'rif. useEffect — komponentni tashqi tizim bilan sinxronlashtirish (data fetch, subscription, DOM API, timer) uchun ishlatiladigan hook. U render tugagandan keyin (commit'dan so'ng, ekran chizilgach) ishlaydi.

Mexanizm. Uch xil rejim, dependency array'ga qarab:

  • [] (bo'sh) — faqat mount'da bir marta ishlaydi, unmount'da cleanup.
  • [a, b] — mount'da va har a yoki b o'zgarganda ishlaydi.
  • massiv yo'q — har render'dan keyin ishlaydi.

Cleanup funksiyasi (return () => ...) keyingi effekt ishlashidan oldin va unmount'da chaqiriladi — eski subscription/timer'ni tozalash uchun. Ya'ni tsikl: effect (deps o'zgarsa) cleanup effect ... unmount'da cleanup.

Kod misol.

jsx
useEffect(() => {
  const id = setInterval(() => tick(), 1000);
  return () => clearInterval(id);   // cleanup — eski timerni tozalaydi
}, []);                              // faqat mount/unmount

useEffect(() => {
  const ctrl = new AbortController();
  fetch(`/api/user/${userId}`, { signal: ctrl.signal }).then(/*...*/);
  return () => ctrl.abort();         // userId o'zgarsa eski so'rovni bekor qiladi
}, [userId]);

Keng tarqalgan xato. Dependency array'ni to'liq to'ldirmaslik. Effekt ichida ishlatilgan har bir reaktiv qiymat (props, state, funksiya) massivda bo'lishi shart — aks holda stale (eskirgan) qiymat ustida ishlaysiz. eslint-plugin-react-hooks shu xatolarni tutadi.

Follow-up. "useEffect ni render vaqtida hisoblash uchun ishlatsak bo'ladimi?" Yo'q. Hosila qiymatlar (derived state) render paytida hisoblanishi kerak, effekt esa faqat yon ta'sir (side effect) uchun. "Effect kerakmasmi?" — avval o'ylab ko'ring.


S: useLayoutEffect useEffectdan qanday farq qiladi va qachon kerak? (Senior)

J: Ta'rif. Ikkalasi ham effekt, farq — vaqtida (timing). useEffect — brauzer ekranni chizgandan keyin (asinxron, non-blocking) ishlaydi. useLayoutEffect — DOM o'zgargandan keyin, lekin brauzer chizishdan oldin (sinxron, blocking) ishlaydi.

Mexanizm. React commit fazasida: DOM mutatsiya useLayoutEffect (sinxron, bu yerda DOM'ni o'lchash/tuzatish mumkin) brauzer paint useEffect (paint'dan keyin). Shuning uchun DOM o'lchamini o'qib, darhol pozitsiyani to'g'irlash kerak bo'lsa (tooltip joylashuvi, scroll pozitsiya) useLayoutEffect ishlatiladi — aks holda foydalanuvchi "sakrash" (flicker) ni ko'radi.

Kod misol.

jsx
useLayoutEffect(() => {
  const { height } = ref.current.getBoundingClientRect();
  setTooltipTop(-height);   // paint'dan OLDIN tuzatiladi — sakrash yo'q
}, []);

Keng tarqalgan xato. Hamma joyda useLayoutEffect ishlatish. U sinxron va main thread'ni bloklaydi sekinlashtiradi. 95% holatda useEffect to'g'ri; useLayoutEffect faqat vizual sakrashni tuzatish uchun.

Follow-up. "SSR'da useLayoutEffect nega ogohlantirish beradi?" Server'da DOM va layout bosqichi yo'q; shuning uchun serverda u ishlamaydi va React ogohlantiradi.


S: useMemo va useCallback farqi va qachon ishlatiladi? (Middle)

J: Ta'rif. Ikkalasi ham memoizatsiya (natijani keshlash) hooki. useMemoqiymatni (hisoblash natijasi) keshlaydi. useCallbackfunksiyani keshlaydi. Aslida useCallback(fn, deps) === useMemo(() => fn, deps).

Mexanizm. Har render'da komponent ichidagi hamma narsa qaytadan yaratiladi — jumladan funksiyalar va obyektlar yangi havola (reference) oladi. Bu odatda muammo emas, lekin: (1) og'ir hisoblash har render'da takrorlanmasligi uchun useMemo; (2) funksiya/obyekt React.memo bilan o'ralgan bolaga prop bo'lib borsa, yangi havola bolani behuda re-render qiladi — buni to'xtatish uchun useCallback/useMemo.

Kod misol.

jsx
// Og'ir hisoblashni keshlash:
const sorted = useMemo(() => bigList.slice().sort(cmp), [bigList]);

// Funksiya havolasini barqaror saqlash (memo'langan bola uchun):
const handleSelect = useCallback((id) => setSelected(id), []);
return <MemoizedList items={sorted} onSelect={handleSelect} />;

Keng tarqalgan xato. Hamma narsani useMemo/useCallback bilan o'rash. Memoizatsiya ham narx (xotira + solishtirish). Agar bola React.memo bilan o'ralmagan yoki hisoblash arzon bo'lsa — foydasi yo'q, faqat kodni murakkablashtiradi.

Follow-up. "React 19 Compiler kelgach, useMemo/useCallback kerakmi?" React Compiler avtomatik memoizatsiya qiladi, shuning uchun ko'p qo'lda memoizatsiya ortiqcha bo'lib qoladi.


S: useRef nima uchun kerak va state'dan qanday farq qiladi? (Middle)

J: Ta'rif. useRef — render'lar orasida saqlanadigan, o'zgaruvchan (mutable) "quti" ({ current: ... }) qaytaradi. Ikki asosiy vazifa: (1) DOM elementiga havola, (2) re-render keltirmaydigan qiymatni saqlash.

Mexanizm. ref.current ni o'zgartirish re-render keltirmaydi — state'dan asosiy farqi shu. Ref render'lar orasida bir xil obyekt bo'lib qoladi (identity saqlanadi). Shuning uchun timer ID, oldingi qiymat (previous value), yoki "bu birinchi render emas" kabi render'ga ta'sir qilmaydigan ma'lumotlar uchun ideal.

Kod misol.

jsx
// DOM'ga murojaat:
const inputRef = useRef(null);
useEffect(() => inputRef.current.focus(), []);
<input ref={inputRef} />

// Render'ga ta'sir qilmaydigan qiymat (interval ID):
const timerRef = useRef(null);
timerRef.current = setInterval(...);   // bu re-render qilmaydi

Keng tarqalgan xato. Ekranda ko'rinishi kerak bo'lgan ma'lumotni refda saqlash. Ref o'zgarsa UI yangilanmaydi. UI'ga ta'sir qiladigan narsa — state, ta'sir qilmaydigan narsa — ref.

Follow-up. "Render vaqtida ref.current ni o'qish yoki yozish mumkinmi?" Yo'q, tavsiya etilmaydi — render toza (pure) bo'lishi kerak. Ref'ni faqat effekt va handler'larda o'qing/yozing.


S: useContext nima va prop drilling muammosini qanday yechadi? (Middle)

J: Ta'rif. Context — ma'lumotni komponentlar daraxti bo'ylab har bir bosqichga qo'lda prop uzatmasdan yetkazish mexanizmi. useContext shu ma'lumotni istalgan chuqurlikdagi bola'da o'qish imkonini beradi.

Mexanizm. createContext context obyektini yaratadi. <Context.Provider value={...}> daraxtning bir qismini o'raydi. Ostidagi har qanday komponent useContext(Context) bilan eng yaqin Provider'ning valueini o'qiydi. Prop drilling — ma'lumotni 5 qavat oralab, har biriga faqat "uzatish uchun" prop berish muammosi; Context uni tekislaydi.

Kod misol.

jsx
const ThemeContext = createContext('light');

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />   {/* Toolbar theme'ni bilmasa ham, ichidagi tugma oladi */}
    </ThemeContext.Provider>
  );
}
function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>OK</button>;
}

Keng tarqalgan xato. Tez-tez o'zgaradigan qiymatni bitta katta Context'ga solish. Provider value o'zgarganda barcha iste'molchi (consumer) re-render bo'ladi — Context'ni bo'lib (masalan alohida "actions" va "state" context), yoki holat kutubxonasidan foydalanish kerak.

Follow-up. "Context state management'ni to'liq almashtiradimi?" Yo'q. Context — uzatish (transport) mexanizmi, o'zi keshlash/selektor/optimallashtirishni bermaydi. Murakkab global holat uchun Zustand/Redux qulayroq.


S: useReducer qachon useState'dan afzal? (Senior)

J: Ta'rif. useReducer — murakkab state mantig'ini reducer funksiya ((state, action) => newState) orqali boshqaradigan hook. useState'ning kuchliroq shakli.

Mexanizm. State yangilanishi bir necha qism-qiymatga bog'liq yoki keyingi holat oldingi holatga murakkab tarzda tayanganda, mantiqni komponentdan reducer'ga ko'chirish uni testlanadigan, bashoratli qiladi. dispatch funksiyasi barqaror havola (identity o'zgarmaydi) — shuning uchun uni useCallbacksiz bolalarga uzatish xavfsiz. Ba'zan useState+setState orqali "tarqoq" bo'lgan mantiqni bir joyga jamlaydi.

Kod misol.

jsx
function reducer(state, action) {
  switch (action.type) {
    case 'increment': return { count: state.count + 1 };
    case 'reset':     return { count: 0 };
    default:          throw new Error('Noma\'lum action');
  }
}
const [state, dispatch] = useReducer(reducer, { count: 0 });
<button onClick={() => dispatch({ type: 'increment' })}>{state.count}</button>

Keng tarqalgan xato. Reducer ichida state'ni mutatsiya qilish (state.count++). Reducer toza (pure) bo'lishi va yangi obyekt qaytarishi shart — aks holda React o'zgarishni sezmaydi.

Follow-up. "useReducer + useContext birga qanday ishlatiladi?" Reducer state'ni Context orqali tarqatib, mini Redux qurish mumkin (ko'p kutubxona shundan tug'ilgan).


S: Custom hook nima va qachon yoziladi? (Middle)

J: Ta'rif. Custom hook — use bilan boshlanuvchi, ichida boshqa hooklarni ishlatib qayta ishlatiladigan mantiqni ajratadigan oddiy funksiya. Komponent emas — UI qaytarmaydi, mantiq qaytaradi.

Mexanizm. Custom hook holat (state) mantig'ini bo'lishadi, holatning o'zini emas. Ya'ni ikki komponent bir custom hook'ni chaqirsa, ularning har biri alohida, mustaqil state oladi — kod bo'lishiladi, ma'lumot emas. Bu React'ning kompozitsiya (composition) falsafasining o'zagi.

Kod misol.

jsx
function useLocalStorage(key, initial) {
  const [value, setValue] = useState(() => {
    const saved = localStorage.getItem(key);
    return saved ? JSON.parse(saved) : initial;
  });
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);
  return [value, setValue];
}
// Ishlatish: const [name, setName] = useLocalStorage('name', '');

Keng tarqalgan xato. Custom hook'ni use bilan boshlamaslik. Nom konventsiyasi — ESLint linter'ga "bu hook, qoidalarni tekshir" degan signal; getData desangiz linter hook qoidalarini qo'llamaydi.

Follow-up. "Custom hook ichida shart bilan boshqa hook chaqira olasizmi?" Yo'q — hook qoidalari custom hook ichida ham bir xil kuchda.


4-BO'LIM. Re-render va optimizatsiya

S: Komponent aynan qachon re-render bo'ladi? (Middle)

J: Ta'rif. Komponent uchta sababdan qayta render bo'ladi: (1) o'z statei o'zgardi, (2) ota-komponenti re-render bo'ldi, (3) ishlatayotgan context qiymati o'zgardi.

Mexanizm. Eng ko'p e'tibordan chetda qoladigani — ota re-render bo'lsa, barcha bolalar (props o'zgarmasa ham) qayta render bo'ladi. Bu "sukut bo'yicha" xatti-harakat. React bolalarni render qilishni to'xtatmaydi, chunki bolaning props'i o'zgargan-o'zgarmaganini bilish uchun uni solishtirish kerak — bu default'da qilinmaydi (aksincha React.memo qiladi). Muhim: re-render ≠ DOM yangilanishi. Re-render VDOM'ni qayta hisoblaydi; agar natija bir xil bo'lsa, DOM'ga tegilmaydi (reconciliation shuni ta'minlaydi).

Kod misol.

jsx
function Parent() {
  const [n, setN] = useState(0);
  return (
    <>
      <button onClick={() => setN(n + 1)}>{n}</button>
      <Child />   {/* Child props'i o'zgarmasa ham har bosishda render bo'ladi */}
    </>
  );
}

Keng tarqalgan xato. "Re-render — bu sekinlik" deb har render'dan qo'rqish. Ko'p re-render arzon. Muammo faqat og'ir komponent yoki juda tez-tez render bo'lganda paydo bo'ladi. Avval o'lchang (Profiler), keyin optimallang.

Follow-up. "Bolaga <Child /> ni prop (children) sifatida uzatsak, ota re-render bo'lganda u re-render bo'ladimi?" Yo'q — children sifatida yuqorida yaratilgan element havolasi o'zgarmagani uchun React uni qayta render qilmaydi (bepul optimizatsiya).


S: React.memo, useMemo, useCallback optimizatsiya uchun qanday birga ishlaydi? (Senior)

J: Ta'rif. React.memo — komponentni o'raydi va props o'zgarmasa re-render'ni to'xtatadi (props'ni yuzaki/shallow solishtiradi). useMemo/useCallback — o'sha props sifatida uzatiladigan qiymat/funksiya havolasini barqaror saqlaydi, aks holda React.memo foydasiz bo'ladi.

Mexanizm. React.memo props'ni Object.is bilan yuzaki solishtiradi. Obyekt/massiv/funksiya prop'lari har render'da yangi havola oladi memo "o'zgardi" deb o'ylaydi to'xtatolmaydi. Shuning uchun bu uchtasi komanda: memo bola'ni himoyalaydi, useMemo/useCallback unga boradigan referens proplarni barqaror qiladi. Bittasini yolg'iz ishlatish ko'pincha bekor.

Kod misol.

jsx
const Row = React.memo(function Row({ item, onSelect }) {
  return <li onClick={() => onSelect(item.id)}>{item.name}</li>;
});

function List({ items }) {
  // useCallback bo'lmasa, har render'da yangi onSelect  memo behuda
  const onSelect = useCallback(id => console.log(id), []);
  return items.map(it => <Row key={it.id} item={it} onSelect={onSelect} />);
}

Keng tarqalgan xato. React.memo'ni ishlatib, unga baribir har render'da yangi obyekt (style={{...}}) yoki inline funksiya uzatish — memo hech qachon "props bir xil" deb hisoblamaydi, optimizatsiya nolga teng.

Follow-up. "React.memoga ikkinchi argument (areEqual) qachon kerak?" Solishtirish mantig'ini o'zgartirmoqchi bo'lganda (masalan faqat item.id ni solishtirish), lekin ehtiyot bo'ling — noto'g'ri areEqual bug keltiradi.


S: Katta ro'yxatni (10 000+ element) qanday optimallashtirasiz? (Senior)

J: Ta'rif. Yechim — virtualizatsiya (windowing): ekranda ko'rinadigan (viewport) elementlarnigina DOM'ga chizish, qolganini chizmaslik.

Mexanizm. 10 000 <div> DOM'da bo'lsa — mount sekin, xotira katta, scroll laqillaydi. Virtualizatsiya (react-window, TanStack Virtual) faqat ~20 ta ko'rinadigan elementni render qiladi, ular ostiga/ustiga balandligi hisoblab qo'yilgan bo'sh joy (spacer) qo'yadi, shunda scrollbar to'g'ri ko'rinadi. Scroll bo'lganda ko'rinadigan "oyna" (window) suriladi va faqat yangi elementlar chiziladi.

Kod misol.

jsx
import { FixedSizeList } from 'react-window';

<FixedSizeList height={600} itemCount={items.length} itemSize={40} width="100%">
  {({ index, style }) => (
    <div style={style}>{items[index].name}</div>   // style — pozitsiya
  )}
</FixedSizeList>

Keng tarqalgan xato. Virtualizatsiyadan oldin React.memo bilan "optimallashtirishga" urinish. Muammo re-render'da emas, DOM'da 10 000 tugun borligida — memo bu yerda yordam bermaydi.

Follow-up. "Elementlar balandligi turlicha bo'lsa (variable height) nima qilasiz?" VariableSizeList yoki dinamik o'lchov (measure) beradigan kutubxona (TanStack Virtual) ishlatiladi.


5-BO'LIM. Holat boshqaruvi va ma'lumot

S: State management uchun Context, Redux, Zustand — qachon qaysini tanlaysiz? (Senior)

J: Ta'rif. Tanlov holatning hajmi, o'zgarish tezligi va murakkabligiga bog'liq. Universal javob yo'q — masshtabga qarab tanlanadi.

Mexanizm.

  • Context (+useReducer) — kam o'zgaradigan global qiymat (tema, til, auth foydalanuvchi). Tez-tez o'zgarsa — barcha consumer re-render bo'lishi tufayli yomon masshtablanadi (selektor yo'q).
  • Zustand — yengil, kam boilerplate, hook-asosli, selektor bilan aniq re-render nazorati. Kichik-o'rta ilovalar uchun ideal.
  • Redux Toolkit — katta jamoa, murakkab holat, qat'iy struktura, devtools/time-travel, middleware (saga/thunk) kerak bo'lganda. Ko'p boilerplate, lekin bashoratli.

Umumiy qoida: avval local state, keyin lifting up / Context, faqat kerak bo'lsa tashqi kutubxona. Ko'p ilovalar Redux'ni behuda ishlatadi.

Kod misol.

jsx
// Zustand — soddaligi:
import { create } from 'zustand';
const useStore = create((set) => ({
  count: 0,
  inc: () => set((s) => ({ count: s.count + 1 })),
}));
// Komponentda — faqat count o'zgarsa re-render:
const count = useStore((s) => s.count);

Keng tarqalgan xato. Server ma'lumotini (API'dan kelgan) global client store'ga (Redux) solish. Bu keshlash, qayta yuklash, "eskirish" (stale) mantig'ini qo'lda yozishga majbur qiladi — buning uchun alohida vosita (TanStack Query) bor.

Follow-up. "Redux'da nega stateni to'g'ridan-to'g'ri o'zgartirib bo'lmaydi, RTK'da esa state.x = 1 yozamiz?" RTK ichida Immer ishlatiladi — u "mutatsiya"ni ushlab, immutable yangilanishga aylantiradi.


S: Server state va client state farqi nima — nega TanStack Query kerak? (Senior)

J: Ta'rif. Client state — faqat brauzerga tegishli, sinxron holat (modal ochiqmi, forma qiymati, tema). Server state — serverda "egalik qilinadigan", asinxron kelib turadigan, boshqa foydalanuvchilar ham o'zgartira oladigan ma'lumot (user profili, mahsulotlar ro'yxati).

Mexanizm. Server state'ning o'ziga xos muammolari bor: keshlash, fon (background) yangilash, "eskirish" (stale), qayta urinish (retry), bir nechta joyda bir xil so'rovni deduplikatsiya qilish, pagination. Buni useState+useEffect bilan qo'lda yozish — yuzlab qator xatoga moyil kod. TanStack Query (React Query) shu muammolarni maxsus yechadi: har so'rovni query key bilan keshlaydi, avtomatik retry/refetch qiladi, isLoading/isError/data holatlarini beradi.

Kod misol.

jsx
import { useQuery } from '@tanstack/react-query';

function Profile({ id }) {
  const { data, isLoading, isError } = useQuery({
    queryKey: ['user', id],
    queryFn: () => fetch(`/api/user/${id}`).then(r => r.json()),
    staleTime: 60_000,   // 1 daqiqa "yangi" hisoblanadi, refetch qilmaydi
  });
  if (isLoading) return <Spinner />;
  if (isError)   return <Error />;
  return <h1>{data.name}</h1>;
}

Keng tarqalgan xato. Server ma'lumotini useEffect + useState bilan olib, keyin uni bir necha komponentda takror so'rash. Kesh yo'qligi tufayli har mount'da qaytadan fetch, "waterfall" so'rovlar va race condition'lar chiqadi.

Follow-up. "staleTime va cacheTime (gcTime) farqi?" staleTime — ma'lumot qachongacha "yangi" (refetch qilinmaydi); gcTime — foydalanilmayotgan kesh xotirada qancha turadi.


6-BO'LIM. Naqshlar (patterns)

S: Error Boundary nima va nega hookda yozib bo'lmaydi? (Middle)

J: Ta'rif. Error Boundary — bola komponentlarda render vaqtida yuzaga kelgan JS xatosini ushlab, butun ilova qulashining oldini oladigan va zaxira UI (fallback) ko'rsatadigan komponent.

Mexanizm. U ikkita maxsus lifecycle metodiga tayanadi: static getDerivedStateFromError (fallback ko'rsatish uchun state'ni yangilaydi) va componentDidCatch (xatoni loglaydi). Hozircha bu metodlarning hook ekvivalenti yo'q, shuning uchun Error Boundary faqat class komponent sifatida yoziladi (yoki react-error-boundary kutubxonasi ishlatiladi).

Kod misol.

jsx
class ErrorBoundary extends React.Component {
  state = { hasError: false };
  static getDerivedStateFromError() { return { hasError: true }; }
  componentDidCatch(error, info) { logError(error, info); }
  render() {
    return this.state.hasError ? <h2>Xatolik yuz berdi</h2> : this.props.children;
  }
}
// <ErrorBoundary><App /></ErrorBoundary>

Keng tarqalgan xato. Error Boundary hamma xatoni tutadi deb o'ylash. U tutmaydi: event handler ichidagi xatolar, asinxron kod (setTimeout), SSR, va boundary'ning o'zidagi xato. Handler xatolari uchun oddiy try/catch kerak.

Follow-up. "Bir necha error boundary joylashtirsak nima bo'ladi?" Xato eng yaqin boundary'da ushlanadi — shuning uchun ilovaning turli qismlarini alohida o'rab, bittasi qulaganda qolgani ishlashda davom etadi.


S: Portal nima va qachon kerak? (Middle)

J: Ta'rif. Portal — bola komponentni React daraxtida joyida qoldirib, uni DOM'da boshqa joyga (masalan document.bodyga) chizish imkonini beradi.

Mexanizm. Modal, tooltip, dropdown kabi elementlar ko'pincha ota-elementning overflow: hidden, z-index yoki transformiga "qamalib" qoladi. Portal DOM tugunini bodyga ko'chiradi — shunda u har qanday konteynerdan "chiqib", to'g'ri joylashadi. Muhim: portal DOM'da ko'chsa ham, React daraxtida eski joyida qoladi — shuning uchun context, event bubbling (React sintetik hodisalari) React ierarxiyasi bo'yicha ishlaydi, DOM joylashuvi bo'yicha emas.

Kod misol.

jsx
import { createPortal } from 'react-dom';

function Modal({ children, onClose }) {
  return createPortal(
    <div className="overlay" onClick={onClose}>
      <div className="modal">{children}</div>
    </div>,
    document.body,   // DOM'da body'ga chiziladi
  );
}

Keng tarqalgan xato. Portal DOM'da tashqarida bo'lgani uchun uning ichidagi tugma bosilganda event ota-komponentga yetmaydi deb o'ylash. Aslida React hodisalari komponent daraxti bo'yicha ko'tariladi — portal ichidagi klik React'da eski ota'ga baribir yetadi.

Follow-up. "Portal SSR bilan qanday ishlaydi?" Server'da document yo'q, shuning uchun portal odatda useEffect ichida (client'da) faollashtiriladi yoki Next.js'da mos yechim ishlatiladi.


S: Lazy loading, code splitting va Suspense qanday birga ishlaydi? (Middle)

J: Ta'rif. Code splitting — bitta katta JS bundle'ni kerak bo'lganda yuklanadigan kichik bo'laklarga bo'lish. React.lazy — komponentni faqat kerak bo'lganda import qiladi. Suspense — lazy komponent yuklanayotganda ko'rsatiladigan fallback'ni beradi.

Mexanizm. React.lazy(() => import('./X')) — dinamik import() qaytaradi, bundler (Vite/webpack) buni alohida chunk qilib ajratadi. Komponent birinchi ko'rsatilishi kerak bo'lganda chunk tarmoq orqali yuklanadi; shu paytda Suspense fallbackni chizadi. Yuklanib bo'lgach, React haqiqiy komponentni ko'rsatadi. Bu boshlang'ich yuklanish (initial load) hajmini kamaytiradi.

Kod misol.

jsx
const Dashboard = React.lazy(() => import('./Dashboard'));

function App() {
  return (
    <Suspense fallback={<Spinner />}>
      <Dashboard />   {/* alohida chunk, kerak bo'lganda yuklanadi */}
    </Suspense>
  );
}

Keng tarqalgan xato. React.lazy'ni Suspensesiz ishlatish — komponent yuklanayotganda React nima ko'rsatishni bilmay xato beradi. Har lazy komponentni (yoki guruhini) Suspense bilan o'rash shart.

Follow-up. "Route darajasida code splitting qanday qilinadi?" Har bir sahifa/route'ni React.lazy bilan yuklab, router'ni Suspensega o'rash — eng katta samara shu yerda.


7-BO'LIM. Klassik tuzoqlar (gotchas)

S: Stale closure (eskirgan closure) muammosi nima? (Senior)

J: Ta'rif. Stale closure — effekt yoki callback eski render'dagi state/props qiymatini "eslab qolib", keyingi yangilangan qiymatni ko'rmasligi. React'dagi eng ko'p uchraydigan tuzoqlardan biri.

Mexanizm. Har render — bu funksiyaning yangi chaqiruvi; shu render'dagi state qiymati o'sha render'ning closure'iga "muzlab" qoladi. Agar useEffect(() => setInterval(...), []) bo'sh dependency bilan yozilsa, interval birinchi render'ning closure'ida qoladi va count doim boshlang'ich qiymatda ko'rinadi — garchi ekranda u o'sib borsa ham. Effekt boshqa qiymatni ko'rishi uchun u dependencyda bo'lishi va effekt qayta ishga tushishi kerak.

Kod misol.

jsx
//  Stale closure — count doim 0'da qoladi:
useEffect(() => {
  const id = setInterval(() => setCount(count + 1), 1000);  // count muzlagan
  return () => clearInterval(id);
}, []);   // count deps'da yo'q

//  Updater funksiya — eng oxirgi qiymatni oladi:
useEffect(() => {
  const id = setInterval(() => setCount(c => c + 1), 1000);
  return () => clearInterval(id);
}, []);

Keng tarqalgan xato. Muammoni "count deps'ga qo'shib" yechishga urinish — bu har sekundda interval'ni qayta yaratadi. To'g'ri yechim — updater funksiya (c => c + 1) yoki qiymatni useRefda saqlash.

Follow-up. "Har render'da eng yangi callback'ni saqlab, lekin effektni qayta ishga tushirmaslik uchun qanday naqsh bor?" useRef ichida eng oxirgi callback'ni saqlash (useEffectEvent / "latest ref" naqshi).


S: useEffect cheksiz sikl (infinite loop) qanday yuzaga keladi? (Senior)

J: Ta'rif. Cheksiz sikl — effekt ichida state yangilanadi, bu re-render qiladi, re-render effektni qayta ishga tushiradi, u yana state'ni yangilaydi... to'xtamaydi.

Mexanizm. Ikki asosiy sabab: (1) dependency array'da har render'da yangi havola oladigan obyekt/massiv/funksiya bor — React uni "o'zgardi" deb har safar effektni qayta ishga tushiradi; (2) effekt to'g'ridan-to'g'ri o'zining dependency'sidagi state'ni yangilaydi, shartsiz.

Kod misol.

jsx
//  obj har render'da yangi havola  effekt cheksiz:
const obj = { id };
useEffect(() => { fetchData(obj); }, [obj]);   // obj doim "yangi"

//  ibtidoiy (primitive) qiymatni deps qiling:
useEffect(() => { fetchData({ id }); }, [id]);

//  effekt o'z deps'ini shartsiz yangilaydi:
useEffect(() => { setCount(count + 1); }, [count]);   // cheksiz

Keng tarqalgan xato. Obyekt yoki massivni to'g'ridan-to'g'ri dependency array'ga qo'yish. Havola solishtiruvi (Object.is) tufayli u har safar "o'zgargan" bo'ladi. Yechim: primitiv qiymatlarni ajratib deps qilish yoki useMemo bilan havolani barqarorlashtirish.

Follow-up. "Funksiya dependency bo'lsa, uni qanday barqarorlashtirasiz?" useCallback bilan o'rab, uni deps'ga qo'yish (yoki funksiyani effekt ichiga ko'chirish).


S: setStatedan keyin state darhol yangilanmasligi — bu bug'mi? (Middle)

J: Ta'rif. Yo'q, bu dizayn. setState state'ni joyida o'zgartirmaydi, u keyingi render uchun yangi qiymatni rejalashtiradi. Joriy funksiya ichida state eski (snapshot) qiymatda qoladi.

Mexanizm. React state'ni immutable snapshot deb qaraydi: har render o'z state qiymatiga ega. setState(x) chaqirgach, joriy render'dagi state o'zgarmaydi — faqat React keyingi render'ni x bilan rejalashtiradi. Bir handler ichidagi bir necha setState batch qilinadi (bir re-render). Shuning uchun yangi qiymatni darhol ishlatish kerak bo'lsa — mahalliy o'zgaruvchi yoki updater funksiya ishlatiladi.

Kod misol.

jsx
function handle() {
  setName('Ali');
  console.log(name);   //  hali eski qiymat (masalan '')

  const next = 'Ali';  //  kerak bo'lsa mahalliy o'zgaruvchida ishla
  setName(next);
  doSomething(next);
}

Keng tarqalgan xato. setStatedan keyin darhol stateni o'qib, unga tayanib mantiq qurish. Yangilangan qiymat faqat keyingi render'da mavjud bo'ladi.

Follow-up. "Nima uchun React state'ni sinxron o'zgartirmaydi?" Batching + concurrent rendering: har render'da state barqaror (consistent) bo'lishi, va bir necha yangilanish bitta samarali re-render'ga birlashishi uchun.


S: Batching nima va React 18'da nima o'zgardi? (Senior)

J: Ta'rif. Batching — bir necha setState chaqiruvini bitta re-render'ga birlashtirish. Bu ortiqcha render'larni oldini oladi.

Mexanizm. React 17'gacha batching faqat React hodisalari (onClick, onChange) ichida ishlagan. setTimeout, Promise.then, native event listener ichidagi setState'lar batch bo'lmasdan har biri alohida re-render qilardi. React 18 avtomatik batchingni joriy etdi — endi qayerda bo'lmasin (Promise, timeout, native handler) bir tick ichidagi barcha yangilanishlar birlashtiriladi.

Kod misol.

jsx
// React 18: ikkalasi ham bitta re-render (avval setTimeout ichida 2 ta bo'lardi):
setTimeout(() => {
  setCount(c => c + 1);
  setFlag(f => !f);       // 18'da birgalikda batch  1 render
}, 1000);

// Batching'ni ataylab buzish (kamdan-kam kerak):
import { flushSync } from 'react-dom';
flushSync(() => setCount(1));   // darhol re-render qiladi

Keng tarqalgan xato. React 17 kodini 18'ga o'tkazganda setTimeout ichida har setState alohida render bo'lishiga tayangan mantiq buzilishi mumkin. Odatda bu yaxshilanish, lekin kutilmagan natija bermasin.

Follow-up. "flushSync qachon kerak?" DOM'ni darhol yangilab, keyin o'lchash kerak bo'lganda (masalan yangi element qo'shib, unga scroll qilish) — lekin u batching foydasini yo'qotgani uchun kam ishlatiladi.


S: StrictMode nima va nega effektlar ikki marta ishlaydi? (Middle)

J: Ta'rif. StrictMode — faqat developmentda ishlaydigan, potentsial muammolarni erta topish uchun mo'ljallangan yordamchi "o'rovchi" (wrapper). Production'ga hech qanday ta'sir qilmaydi.

Mexanizm. StrictMode development'da komponentni ikki marta mount qiladi (mount unmount mount) va ba'zi funksiyalarni (render, ba'zi updater'lar) ikki marta chaqiradi. Maqsad — nopok (impure) render va cleanup'siz effektlarni oshkor qilish. Agar effekt to'g'ri cleanup qilsa, ikki marta ishlash zararsiz; qilmasa — buglar (ikki marta subscription, ikki so'rov) ko'rinadi. Bu concurrent rendering'ga tayyorgarlik.

Kod misol.

jsx
// StrictMode buni oshkor qiladi — cleanup bo'lsa muammo yo'q:
useEffect(() => {
  const conn = createConnection();
  conn.connect();
  return () => conn.disconnect();   // cleanup bo'lsa, ikki mount zararsiz
}, []);

Keng tarqalgan xato. "Effekt ikki marta ishlayapti, StrictMode'ni o'chiraman" deb reaksiya qilish. Aslida bu — kodingizda cleanup yo'qligini ko'rsatgan signal. To'g'ri yechim — StrictMode'ni o'chirish emas, cleanup qo'shish.

Follow-up. "Production'da ham effekt ikki marta ishlaydimi?" Yo'q, faqat development + StrictMode'da. Production'da bir marta.


S: Nega JSX'da state massivini push qilib bo'lmaydi? (Middle)

J: Ta'rif. React state'ni immutable (o'zgarmas) deb qaraydi. arr.push(x) massivni joyida o'zgartiradi, lekin havola o'zgarmaydi — shuning uchun React o'zgarishni sezmaydi va re-render qilmaydi.

Mexanizm. React yangi va eski state'ni Object.is bilan havola (reference) bo'yicha solishtiradi. push/splice/sort bir xil massiv obyektini o'zgartiradi havola bir xil React "hech narsa o'zgarmadi" deb render'ni o'tkazib yuboradi. Yangi havola yaratish kerak: spread ([...arr, x]) yoki map/filter/concat.

Kod misol.

jsx
//  Mutatsiya — re-render bo'lmaydi:
const add = (item) => { items.push(item); setItems(items); };

//  Yangi havola:
const add = (item) => setItems(prev => [...prev, item]);
const remove = (id) => setItems(prev => prev.filter(i => i.id !== id));
const update = (id) => setItems(prev => prev.map(i => i.id === id ? {...i, done: true} : i));

Keng tarqalgan xato. Obyekt state'ni ham to'g'ridan-to'g'ri o'zgartirish (user.name = 'Ali'; setUser(user)). Bu ham havolani o'zgartirmaydi. Har doim setUser({...user, name: 'Ali'}).

Follow-up. "Chuqur ichki (nested) obyektni immutable yangilash noqulay — yechim?" Immer (produce) yoki Immer asosli RTK — "mutatsiya yozib, immutable natija olish".


8-BO'LIM. Next.js, SSR va React Server Components

S: CSR, SSR, SSG va ISR farqi nima? (Middle)

J: Ta'rif. Bular sahifani qachon va qaerda HTML'ga aylantirish strategiyalari:

  • CSR (Client-Side Rendering) — server bo'sh HTML + JS beradi, brauzer JS bilan sahifani quradi.
  • SSR (Server-Side Rendering) — server har so'rovda to'liq HTML generatsiya qiladi.
  • SSG (Static Site Generation) — HTML build vaqtida oldindan generatsiya qilinadi.
  • ISR (Incremental Static Regeneration) — SSG, lekin sahifa belgilangan vaqtdan keyin fon'da qayta generatsiya qilinadi.

Mexanizm. CSR'da birinchi ekran bo'sh (yomon SEO, sekin FCP), lekin server yengil. SSR har so'rovda to'liq HTML beradi (yaxshi SEO, dinamik ma'lumot), lekin server yuki katta. SSG eng tez (CDN'dan statik fayl), lekin ma'lumot build vaqtida qotib qoladi. ISR ikkalasini birlashtiradi: statik tezlik + davriy yangilanish.

Kod misol.

jsx
// Next.js App Router — ISR:
export const revalidate = 60;   // har 60 soniyada fon'da qayta generatsiya

async function Page() {
  const data = await fetch('https://api/...', { next: { revalidate: 60 } });
  return <Articles data={await data.json()} />;
}

Keng tarqalgan xato. Hamma sahifani SSR qilish. Blog, hujjatlar kabi kam o'zgaradigan sahifalar uchun SSG/ISR ancha tez va arzon. Strategiyani sahifa turiga qarab tanlang.

Follow-up. "Bir ilova ichida turli sahifalar turli strategiya ishlatsa bo'ladimi?" Ha, Next.js har route uchun alohida strategiya tanlash imkonini beradi (per-route rendering).


S: Hydration nima va "hydration mismatch" xatosi nega chiqadi? (Senior)

J: Ta'rif. Hydration — server generatsiya qilgan statik HTML'ni brauzerda React qayta "jonlantirish" jarayoni: React shu HTML'ga o'z event handler'larini va state'ini "ulaydi", DOM'ni qayta chizmasdan interaktiv qiladi.

Mexanizm. SSR'da server HTML yuboradi (foydalanuvchi darhol ko'radi), keyin JS yuklanib React ishga tushadi. React server bergan HTML aynan o'zi generatsiya qiladigan HTML bilan bir xil deb kutadi va faqat handler'larni biriktiradi. Agar client'da generatsiya qilingan daraxt server'nikidan farq qilsa ("hydration mismatch") — React ogohlantiradi va o'sha qismni qayta chizishga majbur bo'ladi (sekin + vizual sakrash).

Sabab odatda: Date.now(), Math.random(), window/localStorage'ga render vaqtida murojaat, yoki brauzer kengaytmasi HTML'ni o'zgartirishi.

Kod misol.

jsx
//  Server va client har xil HTML  mismatch:
function Clock() { return <span>{new Date().toLocaleTimeString()}</span>; }

//  Faqat client'da ko'rsat:
function Clock() {
  const [time, setTime] = useState(null);
  useEffect(() => setTime(new Date().toLocaleTimeString()), []);
  return <span>{time ?? '...'}</span>;   // server'da '...'
}

Keng tarqalgan xato. Render vaqtida typeof window !== 'undefined' tekshuruvi bilan turli narsa qaytarish — bu aynan mismatch keltiradi (server bir xil, client boshqa). Client-only mantiqni useEffectga qo'ying.

Follow-up. "Hydration'ni tezlashtirish uchun qanday zamonaviy yondashuvlar bor?" Selective/progressive hydration, streaming SSR (Suspense bilan), va React Server Components (JS'ni butunlay yubormaslik).


S: React Server Components (RSC) nima va client komponentdan qanday farq qiladi? (Senior)

J: Ta'rif. RSC — faqat serverda render bo'ladigan, brauzerga JavaScript yubormaydigan komponentlar. Next.js App Router'da komponentlar sukut bo'yicha server komponent; interaktivlik kerak bo'lsa 'use client' bilan client komponent qilinadi.

Mexanizm. Server komponent serverda ishlaydi: to'g'ridan-to'g'ri ma'lumotlar bazasi/API'ga murojaat qila oladi (async bo'lishi mumkin), maxfiy kalitlarni ishlata oladi, va natijasini serialized (RSC payload) ko'rinishida client'ga yuboradi — komponent kodi bundle'ga kirmaydi. Bu bundle hajmini keskin kamaytiradi. Lekin server komponentda useState, useEffect, event handler, brauzer API ishlamaydi — ular faqat client komponentda.

Kod misol.

jsx
// Server Component (default) — DB'ga to'g'ridan-to'g'ri:
async function ProductList() {
  const products = await db.product.findMany();   // serverda
  return <ul>{products.map(p => <ProductCard key={p.id} p={p} />)}</ul>;
}

// Client Component — interaktivlik kerak:
'use client';
function AddToCart({ id }) {
  const [added, setAdded] = useState(false);
  return <button onClick={() => setAdded(true)}>{added ? 'Qo\'shildi' : 'Savatga'}</button>;
}

Keng tarqalgan xato. Server komponentda useState/onClick ishlatishga urinish yoki har faylga keraksiz 'use client' yozish. 'use client' — bu komponent va uning barcha importlari client'ga o'tishini anglatadi; uni interaktivlik chegarasiga imkon qadar pastga qo'ying.

Follow-up. "Server komponent ichiga client komponentni, client ichiga server komponentni joylashtirib bo'ladimi?" Server ichiga client — ha (oddiy). Client ichiga server komponent — faqat children (prop) sifatida uzatib bo'ladi, to'g'ridan-to'g'ri import qilib emas.


9-BO'LIM. Testlash va profiling

S: React Testing Library falsafasi qanday — Enzyme'dan farqi nima? (Middle)

J: Ta'rif. React Testing Library (RTL) — komponentni foydalanuvchi nuqtai nazarida testlash kutubxonasi. Asosiy shior: "test kod ichki tuzilishiga emas, xatti-harakatga (behavior) tayansin".

Mexanizm. Enzyme komponent ichki holatini (state, instance metodlari) tekshirardi — bu refactor'da mo'rt (brittle) testlarga olib keladi. RTL esa DOM'ni foydalanuvchi ko'rganidek so'raydi: matn, rol (role), label bo'yicha element topadi va klik/yozishni simulyatsiya qiladi. Shunda ichki implementatsiya o'zgarsa ham (masalan class hook), test buzilmaydi — chunki u faqat natijani tekshiradi.

Kod misol.

jsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('bosilganda hisoblagich oshadi', async () => {
  render(<Counter />);
  const btn = screen.getByRole('button', { name: /bosildi/i });
  await userEvent.click(btn);
  expect(screen.getByText(/bosildi: 1/i)).toBeInTheDocument();
});

Keng tarqalgan xato. getByTestId'ga haddan tashqari tayanish. Avval rol va matn (foydalanuvchi ko'radigan narsa) bo'yicha so'rang; testId faqat boshqa yo'l bo'lmaganda. Bu accessibility'ni ham rag'batlantiradi.

Follow-up. "getBy, queryBy, findBy farqi?" getBy topmasa xato tashlaydi; queryBy null qaytaradi (yo'qlikni tekshirish uchun); findBy — asinxron, element paydo bo'lishini kutadi (Promise).


S: React ilovasidagi performance muammosini qanday topasiz va yechasiz? (Senior)

J: Ta'rif. Jarayon: o'lchash aniqlash optimallash qayta o'lchash. Taxminga tayanmasdan, avval React DevTools Profiler bilan qaysi komponent, nega, qancha vaqt render bo'layotganini o'lchash.

Mexanizm. Profiler har commit'da qaysi komponent render bo'lgan va necha ms olganini ko'rsatadi ("flame graph"). "Why did this render?" bilan sababni (props/state/context) topasiz. Keyin muammo turiga qarab:

  • Behuda re-render React.memo + useMemo/useCallback, yoki state'ni pastroqga tushirish (colocation).
  • Og'ir hisoblash useMemo, yoki useTransition bilan past ustuvorlikka o'tkazish.
  • Katta ro'yxat virtualizatsiya.
  • Katta bundle code splitting (React.lazy).

Kod misol.

jsx
// Og'ir filtrlashni past ustuvorlikka berish — input laqillamaydi:
const [isPending, startTransition] = useTransition();
function onSearch(q) {
  setQuery(q);                                  // shoshilinch (input)
  startTransition(() => setFiltered(filter(q)));// sekin, uzilishi mumkin
}

Keng tarqalgan xato. O'lchamasdan "optimallash" — hamma joyga memo/useCallback sepish. Bu kodni murakkablashtiradi, ba'zan sekinlashtiradi (memo solishtiruvi ham narx). Profiler tasdiqlagan muammonigina yeching.

Follow-up. "useTransition va useDeferredValue farqi?" useTransition — state yangilashni past ustuvorlikka o'raydi; useDeferredValue — mavjud qiymatni "kechiktirilgan" nusxasi bilan ishlaydi (masalan tashqaridan kelgan prop uchun).


S: Class komponent lifecycle metodlari hook'larda qanday ifodalanadi? (Middle)

J: Ta'rif. Hooklar class lifecycle metodlarini bir-biriga bog'liq mantiqni guruhlab almashtiradi. Bitta useEffect bir necha lifecycle vazifasini birlashtira oladi.

Mexanizm. Moslik:

  • componentDidMount useEffect(() => {...}, [])
  • componentDidUpdate useEffect(() => {...}, [deps])
  • componentWillUnmount useEffect(() => { return () => {...}; }, []) (cleanup)

Farqi: class'da mantiq metodlar bo'yicha tarqalgan edi (subscription didMount'da, tozalash willUnmount'da). Hook'da esa bir tegishli mantiq bitta effektda birga turadi (o'rnatish + tozalash yonma-yon) — bu o'qish va xatoni kamaytiradi.

Kod misol.

jsx
// Class: mantiq 2 metodga bo'lingan:
componentDidMount()    { window.addEventListener('resize', this.onResize); }
componentWillUnmount() { window.removeEventListener('resize', this.onResize); }

// Hook: bir joyda — o'rnatish + tozalash:
useEffect(() => {
  window.addEventListener('resize', onResize);
  return () => window.removeEventListener('resize', onResize);
}, []);

Keng tarqalgan xato. useEffect(() => {...}, [])'ni componentDidMount bilan aynan bir xil deb o'ylash. StrictMode'da u ikki marta ishlaydi, va u paint'dan keyin (didMount esa oldin) ishlaydi — timing farq qiladi.

Follow-up. "getDerivedStateFromProps hook ekvivalenti bormi?" To'g'ridan-to'g'ri yo'q; ko'p holatda render vaqtida hisoblash (derived state) yoki key bilan reset qilish afzal.


S: Fragment nima va nega kerak? (Middle)

J: Ta'rif. Fragment (<></> yoki <React.Fragment>) — bir necha elementni ortiqcha DOM tuguni (wrapper <div>) qo'shmasdan guruhlash imkonini beradi.

Mexanizm. JSX'da komponent bitta root element qaytarshi kerak. Ilgari buning uchun har doim <div>ga o'rash kerak edi — bu keraksiz DOM tugunlarini (<div> osmoni), CSS layout (flex/grid) buzilishini keltirardi. Fragment DOM'da hech qanday tugun qoldirmaydi, faqat bolalarni guruhlaydi.

Kod misol.

jsx
//  Keraksiz div — grid layout'ni buzadi:
function Cells() { return <div><td>A</td><td>B</td></div>; }

//  Fragment — ortiqcha tugun yo'q:
function Cells() { return <><td>A</td><td>B</td></>; }

// key kerak bo'lsa — to'liq shakl:
{items.map(i => <React.Fragment key={i.id}><dt>{i.t}</dt><dd>{i.d}</dd></React.Fragment>)}

Keng tarqalgan xato. Ro'yxatda qisqa <> sintaksisiga key berishga urinish — u prop qabul qilmaydi. key kerak bo'lsa to'liq <React.Fragment key={...}> yozing.

Follow-up. "Nega har render'da ortiqcha <div> performance'ga yomon?" DOM daraxti chuqurlashadi, CSS hisoblash va reconciliation biroz og'irlashadi; katta ro'yxatda bu sezilarli bo'ladi.


S: children prop nima va composition naqshi nima? (Middle)

J: Ta'rif. children — komponent teglari ichiga yozilgan narsani beruvchi maxsus prop. Composition (kompozitsiya) — komponentlarni prop drilling o'rniga bir-birining ichiga joylashtirib qurish naqshi.

Mexanizm. <Card><p>Salom</p></Card> yozganda <p>Salom</p> Card'ning props.childreniga tushadi. Bu "slot" mexanizmi: Card ichida nima borligini bilmasdan uni o'rab, dizayn beradi. Composition prop drilling'ni kamaytiradi — chunki oraliq komponent ma'lumotni uzatmaydi, faqat joylashtiradi. Bundan tashqari children bo'lib uzatilgan element yuqorida yaratilgani uchun ota re-render bo'lganda qayta render bo'lmaydi (bepul optimizatsiya).

Kod misol.

jsx
function Card({ title, children }) {
  return (
    <section className="card">
      <h2>{title}</h2>
      <div className="body">{children}</div>   {/* slot */}
    </section>
  );
}
// <Card title="Profil"><Avatar /><Bio /></Card>

Keng tarqalgan xato. Har narsani props orqali uzatib, chuqur prop drilling yaratish. Ko'p holatda komponentni children bilan ochiq (open) qilish — moslashuvchanroq va toza yechim.

Follow-up. "Bir necha 'slot' kerak bo'lsa (header, footer alohida) nima qilasiz?" children'dan tashqari alohida prop'lar (header, footer) sifatida element uzatish — "named slots" naqshi.


S: Nega React'da class o'rniga className, for o'rniga htmlFor yozamiz? (Junior)

J: Ta'rif. JSX — HTML emas, JavaScript. class va for — JavaScript'ning band qilingan so'zlari (reserved words), shuning uchun React DOM proplari uchun className va htmlFor ishlatadi.

Mexanizm. JSX oxir-oqibat React.createElement'ga aylanadi va proplar JS obyekti kaliti bo'ladi. class kalit sifatida ziddiyat keltirardi (ES ichida band). Shuningdek JSX DOM atributlarini emas, DOM proplarini aks ettiradi — ular camelCase'da (onClick, tabIndex, readOnly). Bu HTML'dan farqli, lekin JS bilan mos.

Kod misol.

jsx
<label htmlFor="email" className="lbl">Email</label>
<input id="email" onClick={handle} tabIndex={0} readOnly />
// HTML: class, for, onclick, tabindex, readonly — JSX'da boshqacha

Keng tarqalgan xato. HTML'dan nusxa ko'chirganda class=, onclick= qoldirish — React ogohlantiradi yoki ishlamaydi. Inline style ham obyekt bo'ladi: style={{ color: 'red' }}, string emas.

Follow-up. "aria-* va data-* atributlari ham camelCase'ga o'tadi?" Yo'q — aria-label, data-id HTML'dagi kabi tire (dash) bilan yoziladi (istisno).


S: Prop drilling'ni hal qilishning barcha yo'llari va har birining chegarasi? (Senior)

J: Ta'rif. Prop drilling — ma'lumotni oraliq komponentlar orqali faqat "uzatish uchun" ko'p qavat pastga o'tkazish. Yechimlar: composition, Context, holat kutubxonasi.

Mexanizm. Har birining o'rni:

  1. Composition (children) — eng arzon, ko'p holatda yetarli. Ma'lumot egasi komponentni children bilan o'rasa, oraliq qavatlar hech narsani uzatmaydi.
  2. Context — ma'lumot "keng, lekin kam o'zgaruvchi" bo'lsa (tema, auth, til). Tez-tez o'zgarsa — barcha consumer re-render (selektor yo'q).
  3. Holat kutubxonasi (Zustand/Redux) — global, murakkab, tez o'zgaruvchi holat; selektor bilan aniq re-render.

Qoida: avval composition, keyin Context, oxirgida kutubxona. Ko'pincha "Context'ga o'tdim" degan muammo aslida composition bilan hal bo'ladi.

Kod misol.

jsx
//  Prop drilling — user 3 qavat oralaydi:
<Page user={user}><Sidebar user={user}><Menu user={user} /></Sidebar></Page>

//  Composition — oraliq qavatlar user'ni bilmaydi:
<Page><Sidebar><Menu user={user} /></Sidebar></Page>
// yoki Context: <UserContext.Provider value={user}>...</UserContext.Provider>

Keng tarqalgan xato. Har qanday prop drilling'ni darhol Context bilan almashtirish. 1-2 qavat drilling normal; Context haddan tashqari ishlatilsa, komponentlar "ko'zga ko'rinmas" bog'liqliklar bilan testlash qiyin bo'ladi.

Follow-up. "Context qiymati o'zgarganda re-render'ni qanday cheklaysiz?" Context'ni bo'lish (state va dispatch alohida), yoki selektor beruvchi kutubxona (use-context-selector, Zustand) ishlatish.


Eng ko'p so'raladigan 10 savol

Vaqtingiz kam bo'lsa — avval shu 10 tasini mukammal o'zlashtiring. Bular deyarli har React intervyusida uchraydi:

  1. Virtual DOM nima va reconciliation qanday ishlaydi? — React'ning yuragi; diffing, key, tip solishtirish.
  2. useState nega asinxron ko'rinadi va updater funksiya qachon kerak? — batching + snapshot modeli.
  3. useEffect dependency array va cleanup qanday ishlaydi? — eng ko'p xato qilinadigan hook.
  4. Stale closure nima va qanday oldini olasiz? — senior'ni junior'dan ajratadigan tuzoq.
  5. Komponent qachon re-render bo'ladi va qanday optimallash mumkin?React.memo + useMemo/useCallback uchligi.
  6. key nima uchun kerak va nega index yomon? — reconciliation bilan bog'liq amaliy savol.
  7. Controlled va uncontrolled komponent farqi? — formalar bilan ishlashda asosiy.
  8. Context va state management (Redux/Zustand) — qachon qaysi? — arxitektura qarori.
  9. Server state va client state farqi (TanStack Query nega kerak)? — zamonaviy React'da muhim.
  10. SSR/CSR/SSG/ISR, hydration va RSC farqi (Next.js)? — full-stack darajasidagi savol.

Oxirgi maslahat. Intervyuer javobingizdan keyin doim "nega?" yoki "agar X bo'lsa-chi?" deb so'raydi. Shuning uchun har mavzuni ichki mexanizmigacha (React aynan nima qilyapti) tushuning — yodlangan ta'rif birinchi follow-up'da qulaydi. Bilmagan narsangizni "bilmayman, lekin shunday o'ylayman..." deb ochiq ayting — bu senior belgisi.

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Texnik intervyu: React (+ Next.js asoslari) — Wisar