Custom Hook — nima, qanday yoziladi, qoidalar

~20 daq · React · Hooks — Ilg'or

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:

  1. Nomi use bilan boshlanadi — useFetch, useLocalStorage, useDebounce
  2. Ichida boshqa hook lar ishlatilishi mumkin — useState, useEffect va 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