Custom Hook — nima, qanday yoziladi, qoidalar
Muammo: bir xil mantiq ko'p joyda takrorlanadi
Siz bir nechta komponentda server dan ma'lumot olasiz. Har birida bir xil kod:
function UserRoyxati() {
const [data, setData] = useState(null);
const [yuklanmoqda, setYuklanmoqda] = useState(true);
const [xato, setXato] = useState(null);
useEffect(() => {
fetch('/api/users')
.then(r => r.json())
.then(setData)
.catch(err => setXato(err.message))
.finally(() => setYuklanmoqda(false));
}, []);
// ...
}
function MahsulotRoyxati() {
const [data, setData] = useState(null);
const [yuklanmoqda, setYuklanmoqda] = useState(true);
const [xato, setXato] = useState(null);
useEffect(() => {
fetch('/api/mahsulotlar') // faqat URL farq qiladi
.then(r => r.json())
.then(setData)
.catch(err => setXato(err.message))
.finally(() => setYuklanmoqda(false));
}, []);
// ...
}
Ikki komponentda deyarli bir xil 15 qator kod. Agar bu mantiqni o'zgartirish kerak bo'lsa — ikki joyni o'zgartirish kerak. Komponent ko'paysa — muammo kuchayadi.
Custom Hook — bu takrorlanuvchi mantiqni bir joyga chiqarish imkonini beradi.
Custom Hook nima?
Custom Hook — oddiy JavaScript funksiyasi. Lekin ikkita xususiyati bor:
- Nomi
usebilan boshlanadi —useFetch,useLocalStorage,useDebounce - Ichida boshqa hook lar ishlatilishi mumkin —
useState,useEffectva h.k.
Boshqa hech qanday sehrli narsa yo'q. use prefiksi React ga "bu hook, qoidalarga rioya qil" deb aytadi.
useFetch — birinchi custom hook
Yuqoridagi takrorlanuvchi kodni custom hook ga chiqaramiz:
// hooks/useFetch.js
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [yuklanmoqda, setYuklanmoqda] = useState(true);
const [xato, setXato] = useState(null);
useEffect(() => {
// url o'zgarganda qayta so'rov
setYuklanmoqda(true);
setXato(null);
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(r => {
if (!r.ok) throw new Error(`Server xatosi: ${r.status}`);
return r.json();
})
.then(setData)
.catch(err => {
if (err.name !== 'AbortError') setXato(err.message);
})
.finally(() => setYuklanmoqda(false));
return () => controller.abort();
}, [url]);
return { data, yuklanmoqda, xato };
}
Endi komponentlar ancha sodda:
function UserRoyxati() {
const { data, yuklanmoqda, xato } = useFetch('/api/users');
if (yuklanmoqda) return <p>Yuklanmoqda...</p>;
if (xato) return <p>Xato: {xato}</p>;
return (
<ul>
{data.map(u => <li key={u.id}>{u.ism}</li>)}
</ul>
);
}
function MahsulotRoyxati() {
const { data, yuklanmoqda, xato } = useFetch('/api/mahsulotlar');
if (yuklanmoqda) return <p>Yuklanmoqda...</p>;
if (xato) return <p>Xato: {xato}</p>;
return (
<ul>
{data.map(m => <li key={m.id}>{m.nomi}</li>)}
</ul>
);
}
15 qator → 3 qator. Mantiq bir joyda — o'zgartirish kerak bo'lsa faqat useFetch ni o'zgartirish yetarli.
Custom Hook qoidalari
Hook lar uchun React ning ikki qoidasi bor:
1. Faqat komponent yoki boshqa hook ichida chaqiring:
// ✅ To'g'ri — komponent ichida
function App() {
const { data } = useFetch('/api/users');
}
// ✅ To'g'ri — boshqa hook ichida
function useUsers() {
const { data } = useFetch('/api/users');
return data;
}
// ❌ Xato — oddiy funksiya ichida
function maʼlumotOlish() {
const { data } = useFetch('/api/users'); // ishlamaydi
}
2. Loop, shart yoki ichki funksiya ichida chaqirmang:
// ❌ Xato
function App() {
if (loginQilgan) {
const { data } = useFetch('/api/profile'); // shart ichida
}
}
// ✅ To'g'ri — hook har doim chaqiriladi
function App() {
const { data } = useFetch(loginQilgan ? '/api/profile' : null);
}
Nima uchun? React hook larni chaqirilish tartibiga qarab kuzatadi. Agar tartib o'zgarsa — React qaysi hook qaysi state ga tegishli ekanini bilmay qoladi.
Custom Hook — state qaytarmasa ham bo'ladi
Custom Hook har doim state qaytarishi shart emas. Ba'zan faqat mantiqni ajratish uchun yoziladi:
// hooks/useDocumentTitle.js
import { useEffect } from 'react';
function useDocumentTitle(sarlavha) {
useEffect(() => {
const oldingi = document.title;
document.title = sarlavha;
return () => {
document.title = oldingi; // komponent ketganda qaytarish
};
}, [sarlavha]);
}
// Ishlatish
function MahsulotSahifa({ mahsulot }) {
useDocumentTitle(`${mahsulot.nomi} — Do'kon`);
return <div>...</div>;
}
Xulosa
Custom Hook — takrorlanuvchi mantiqni bir joyga chiqarish. Oddiy funksiya, lekin use prefiksi bilan va ichida hook ishlatiladi.
Takrorlanuvchi mantiq bor?
│
▼
Custom Hook ga chiqar
│
├── nom: use bilan boshlanadi
├── ichida: useState, useEffect va h.k.
└── qaytaradi: komponentga kerakli narsalar
Qoidalar:
- Faqat komponent yoki hook ichida chaqiring
- Loop, shart ichida chaqirmang
Keyingi dars
25-dars: Custom Hook — useFetch, useLocalStorage, useDebounce