React Hooklari — sinflar yozmasdan funksional komponentlarda holat, effektlar, kontekst va React-ning boshqa imkoniyatlaridan foydalanishga imkon beruvchi funksiyalardir. React 16.8 da taqdim etilgan hooklar, HOC va render props kabi murakkab naqshlarni almashtirib, dasturlashga yondashuvni tubdan o‘zgartirdi. React, 2024 ga ko‘ra, komponentni boshqarishning barcha stsenariylarini qamrab oluvchi 15 ta o‘rnatilgan hook mavjud.
Asosiy
React Hooklari — sinflar yaratmasdan freymvorkning ichki mexanizmlariga ‘‘ulanish’’ imkonini beruvchi React-ga o‘rnatilgan funksiyalar to‘plamidir. React 16.8 dan oldin funksional komponentlar faqat props qabul qilishi va JSX qaytarishi mumkin edi — har qanday murakkab mantiq sinf komponentini talab qilardi.
Sinf komponentlarining muammosi — bog‘liq mantiqning ajratilishi. Bir ob‘ektga tegishli kod (masalan, WebSocket obunasi) majburiy ravishda componentDidMount, componentDidUpdate va componentWillUnmount o‘rtasida bo‘lingan edi. Hooklar buni hal qiladi: barcha mantiq bir useEffect-da guruhlanadi.
Ikkinchi muammo — mantiqni qayta ishlatish. Sinf komponentlari o‘rtasida holat mantig‘ini qayta ishlatish uchun HOC (yuqori darajali komponentlar) yoki render props qo‘llanilishi kerak edi — ikkala naqsh ham komponent daraxtida qo‘shimcha ichki ichalik yaratardi. Maxsus hooklar bu muammoni ichki ichaliksiz hal qiladi.
useState — eng asosiy hook. Boshlang‘ich qiymatni qabul qiladi va kortaj qaytaradi: joriy qiymat va uni yangilash uchun funksiya. Sinflardagi this.setState dan farqli o‘laroq, useState ob‘ektlarni birlashtirmaydi — yangi holat ma’lum bir useState chaqiruvi uchun oldingi holatni to‘liq almashtiradi.
import React, { useState } from 'react';
function Form() {
const [text, setText] = useState('');
const [submitting, setSubmitting] = useState(false);
async function handleSubmit() {
setSubmitting(true);
await fetch('/api/submit', {
method: 'POST',
body: JSON.stringify({ text })
});
setSubmitting(false);
}
return (
<div>
<input
value={text}
onChange={e => setText(e.target.value)}
/>
<button onClick={handleSubmit}
disabled={submitting}>
{submitting ? 'Saving...' : 'Submit'}
</button>
</div>
);
}
useState ning setteri oldingi qiymatni oluvchi va yangisini qaytaruvchi funksiyani qabul qilishi mumkin. Funksional shakl yangi holat oldingisidan hisoblanganda va setState ning to‘plangan chaqiruvlari mumkin bo‘lganda majburiydir — har bir chaqiruv dolzarb oldingi qiymatni oladi.
useEffect — funksional komponentlarda yon ta’sirlarni bajarish uchun hook. Ikki argumentni qabul qiladi: effekt funksiyasi va bog‘liqliklar massivi. React effektni har bir renderdan so‘ng bajaradi, lekin bog‘liqliklar ko‘rsatilganda — faqat ulardan birortasi o‘zgarganda.
Bo‘sh bog‘liqliklar massivi [] effekt birinchi renderdan so‘ng bir marta bajarilishini bildiradi (componentDidMount analogi). Effektdan funksiya qaytarish cleanup hisoblanadi, u komponent o‘chirilganda (componentWillUnmount analogi) va effekt qayta bajarilishidan oldin ishlaydi.
import React, { useState, useEffect } from 'react';
function ChatRoom({ roomId }) {
const [messages, setMessages] = useState([]);
useEffect(() => {
const socket = new WebSocket(`wss://chat/${roomId}`);
socket.onmessage = (event) => {
setMessages(prev => [...prev, JSON.parse(event.data)]);
};
// Cleanup - soketni yopish
return () => socket.close();
}, [roomId]);
return <ul>
{messages.map((msg, i) =>
<li key={i}>{msg.text}</li>
)}
</ul>;
}
useEffect ning bog‘liqliklari — effekt va tashqi dunyo o‘rtasidagi yagona aloqadir. Agar effektda props yoki holatdan o‘zgaruvchi ishlatilsa, u bog‘liqliklar massivida bo‘lishi kerak. Ushbu qoidani e‘tiborsiz qoldirish eskirgan ma’lumotlar bilan (stale closure) bog‘liq xatolarning manbaidir.
useContext — kontekst qiymatini o‘qish uchun hook. React.createContext bilan yaratilgan kontekst ob‘yektini qabul qiladi va joriy qiymatni qaytaradi. Kontekst o‘zgarsa, komponent avtomatik ravishda yangi qiymat bilan qayta render qilinadi.
useContext paydo bo‘lishidan oldin funksional komponentlarda kontekstga kirish Context.Consumer da o‘ramni talab qilardi, bu ichki ichalik yaratardi. useContext Consumer-ni butunlay yo‘q qiladi — hook-ni funksional komponentning istalgan joyida chaqirish kifoya.
import React, { createContext, useContext } from 'react';
const ThemeContext = createContext('ochiq');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button
className={`btn btn-${theme}`}
>
{theme === 'dark' ? 'moon' : '☀️'}
</button>;
}
useContext Redux yoki global holatning o‘rnini bosmaydi. React kontekstdan kamdan-kam o‘zgaradigan qiymatlar uchun foydalanishni tavsiya qiladi — mavzu, til, avtorizatsiya. Tez-tez yangilanadigan ma’lumotlar uchun har bir qayta render kontekstning barcha iste’molchilarini qayta hisoblaydi, bu esa ishlashni pasaytirishi mumkin.
useReducer — murakkab yangilash mantig‘iga ega holatlar uchun useState ga alternativ. Reducer funksiyasi va boshlang‘ich holatni qabul qiladi, joriy holat va dispatch funksiyasini qaytaradi. Reducer joriy holat va aksiyani qabul qilib, yangi holatni qaytaradi — yon ta’sirlarsiz toza funksiya.
useReducer ayniqsa bir nechta aksiya (set, reset, increment, addItem) bir holatni boshqarganda foydalidir. Turli setterlar bilan bir nechta useState o‘rniga — aniq aksiya turlari bilan bitta reducer. Bu mantiqni bashorat qilish mumkin va oson sinab ko‘rish mumkin qiladi.
import React, { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + 1 };
case 'setStep':
return { ...state, step: action.step };
case 'reset':
return { count: 0, step: 1 };
default:
throw new Error('Unknown action: ' + action.type);
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, {
count: 0,
step: 1
});
return (
<>
<p>Count: {state.count}</p>
<button
onClick={() => dispatch({ type: 'increment' })}>+</button>
<button
onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</>
);
}
useRef renderlar o‘rtasida saqlanadigan o‘zgaruvchan ob‘yekt yaratadi. current ni o‘zgartirish qayta renderga sabab bo‘lmaydi. Asosiy qo‘llanilishi — DOM elementlariga kirish va o‘zgaruvchan qiymatlarni saqlash (taymerlar, oldingi qiymatlar, kutubxona nusxalari).
useMemo funksiya natijasini yodda saqlaydi. Qiymatni faqat bog‘liqliklardan biri o‘zgarganda qayta hisoblaydi. Qimmat hisob-kitoblar uchun foydalaning — katta massivlarni filtrlash, saralash, ma’lumotlarni formatlash. useCallback — funksiyalarni yodda saqlash uchun useMemo ning maxsus holati.
import React, { useRef, useMemo, useCallback } from 'react';
function SearchPage({ items, query, onItemSelect }) {
const inputRef = useRef(null);
// Mount qilishda avtofokus
useEffect(() => {
inputRef.current?.focus();
}, []);
// Filtrlangan natijani yodda saqlash
const filtered = useMemo(() => {
return items.filter(item =>
item.name.toLowerCase()
.includes(query.toLowerCase())
);
}, [items, query]);
// Callback-ni yodda saqlash
const handleSelect = useCallback((id) => {
onItemSelect(id);
}, [onItemSelect]);
return (
<div>
<input ref={inputRef}
value={query}
onChange={e => setQuery(e.target.value)}
/>
<ul>
{filtered.map(item =>
<li key={item.id}>
<button
onClick={() => handleSelect(item.id)}>
{item.name}
</button>
</li>
)}
</ul>
</div>
);
}
Muhim qoida: useRef, useMemo va useCallback — optimallashtirish vositalari, majburiy konstruksiyalar emas. Hammasini useMemo ga o‘ramang — avval ishlashni o‘lchang. Erta optimallashtirish kodni murakkablashtiradi. React komponentlarni tez render qiladi; useMemo faqat hisob-kitoblar haqiqatan ham qimmat bo‘lganda kerak (O(n²) va yuqori).
React hooklar uchun ikkita qat‘iy qoida kiritdi. Birinchisi: hooklarni faqat yuqori darajada chaqiring — shartlar, sikllar yoki ichki funksiyalar ichida emas. Ikkinchisi: hooklarni faqat React funksional komponentlaridan yoki maxsus hooklardan chaqiring. ESLint plagini eslint-plugin-react-hooks ikkala qoidani avtomatik tekshiradi.
Eng tez-tez uchraydigan xato — hooklarni chaqirish tartibining buzilishi. React renderlar o‘rtasida hooklarni chaqirish tartibiga tayanadi. Agar hook shart ichida bo‘lsa va renderlardan birida chaqirilmagan bo‘lsa, barcha keyingi hooklar siljiydi va xatolarga sabab bo‘ladi.
| Xato | Nima bo‘ladi | Yechim |
|---|---|---|
| Shartdagi hook | Hooklar tartibi buziladi | Shart mantig‘ini hook ichiga köchiring |
| Stale closure | Effekt eski qiymatdan foydalanadi | Barcha bog‘liqliklarni massivga qo‘shing |
| Cheksiz sikl | Bog‘liqliksiz useEffect holatni o‘zgartiradi | Bog‘liqliklarni belgilang yoki useReducer dan foydalaning |
| Renderda ref ni o‘zgartirish | Funksiya tanasida yon ta’sir | Mutatsiyalarni useEffect ga köchiring |
Ikkinchi tez-tez uchraydigan xato — useEffect da stale closure. Agar effektda bog‘liqliklarda ko‘rsatilmagan o‘zgaruvchi ishlatilsa, effekt yopilish momentidagi qiymatini ‘‘ushlab oladi’’. Yechim — ishlatilgan barcha o‘zgaruvchilarni doimo bog‘liqliklar massiviga qo‘shing. Agar bog‘liqliklar juda köp bo‘lsa, effektni bir necha qismga bo‘ling.
Tez-tez beriladigan savollar
React hooklarni chaqirish tartibiga tayanadi renderlar o‘rtasida. Hook shartda chaqirilgan bo‘lsa va renderlardan birida ishlamagan bo‘lsa, barcha keyingi hooklar ‘‘siljiydi’’ — ularning holati aralashadi. ESLint qoidasi hooks/exhaustive-deps bu haqda ogohlantiradi.
useLayoutEffect sinxron va brauzer o‘zgarishlarni chizishidan oldin bajariladi. useEffect asinxron — chizishdan keyin. useLayoutEffect faqat foydalanuvchi o‘zgarishlarni ko‘rishidan oldin DOM ni o‘lchash yoki o‘zgartirish kerak bo‘lganda foydalaning (popover joylashuvi, skrollni tiklash).
useEffect ichida AbortController dan foydalaning. Controller yarating, signal ni fetch ga uzating va cleanup funksiyasida controller.abort() ni chaqiring. Eski brauzerlar uchun cancelled bayrog‘i yetarli: return () => { cancelled = true; } setState dan oldin tekshirish bilan.
Maxsus hook — use prefiksi bilan JavaScript funksiyasi, o‘rnatilgan hooklardan foydalanadi. Xuddi shu hook mantig‘i ikki yoki undan ko‘p komponentlarda takrorlanganda yarating. Misollar: useDebounce, useLocalStorage, useMediaQuery. Maxsus hooklar HOC va render props ni almashtiradi.
Strict Mode da React tozalanmagan effektlar bilan bog‘liq xatolarni topish uchun rivojlanish rejimida komponentni ataylab ikki marta montaj qiladi va o‘chiradi. Cleanup to‘g‘ri yozilgan bo‘lsa, ikki marta chaqirish muammo keltirmaydi. Ishlab chiqarish rejimida bu sodir bo‘lmaydi.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.
Shuningdek o'qing