Hookların Qaydaları

Hooklar React 16.8-ə əlavə olunan yenilikdir. Hooklar ilə klas yazmadan state və ya digər React xüsusiyyətlərindən istifadə edə bilərsiniz.

Hookların sadə JavaScript funksiyaları olmasına baxmayaraq bu funksiyaları işlətdikdə iki qaydaya riayət etmək lazımdır. Bu qaydaları avtomatik tətbiq etmək üçün linter plagini təmin edirik:

Hookları Yalnız Ən Yuxarıdan Çağırın

Hookları tsikllar, şərtlər, və ya digər funksiyalardan çağırmayın. Əvəzinə, Hookları hər zaman React funksiyasının ən yuxarısında yazın. Bu qaydaya riayət edərək komponent render edildikdə Hookların eyni sıra ilə çağrıldığını siğortalıyırsınız. Bu sıraya görə React, useStateuseEffect çağırışlarının vəziyyətini qoruya bilir. (Əgər maraqlanırsınızsa, bunun dərindən izahatı haqqında aşağıda danışacağıq.)

Hookları Yalnız React Funksiyalarından Çağırın

Hookları sadə JavaScript funksiyalarından çağırmayın. Əvəzinə:

  • ✅ Hookları React komponentlərindən çağıra bilərsiniz.
  • ✅ Hookları xüsusi Hooklardan çağıra bilərsiniz (Xüsusi hooklar haqqında sonrakı səhifədə öyrənə bilərsiniz).

Bu qaydaya riayət edərək komponentdə olan state-li məntiqin kodda olduğunu görə bilirsiniz.

ESLint Plagini

Biz bu iki qaydanın tətbiq edilməsi üçün eslint-plugin-react-hooks adlı plagin təmin edirik. Siz bu plagini aşağıdakı formada layihənizə əlavə edə bilərsiniz:

npm install eslint-plugin-react-hooks --save-dev
// ESLint konfiqurasiyanız
{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error", // Hook qaydalarını yoxlayın
    "react-hooks/exhaustive-deps": "warn" // Effekt asılılıqlarını yoxlayın
  }
}

Gələcəkdə, biz bu plagini Create React App və digər toolkit-lərdə təmin etmək istəyirik.

Xüsusi hookların yazılmasını bilmək üçün sonrakı səhifəyə keçə bilərsiniz. Bu səhifədə, bu iki qaydanın səbəbini başa salacağıq.

İzahat

Biz bir komponentdə bir neçə State və ya Effect Hookunun istifadə edilməsini əvvəlki bölmələrdə öyrəndik:

function Form() {
  // 1. "name" state dəyişəni işlədin
  const [name, setName] = useState('Abbas');

  // 2. Anketi qorumaq üçün effekt istifadə edin
  useEffect(function persistForm() {
    localStorage.setItem('formData', name);
  });

  // 3. "surname" state dəyişəni işlədin
  const [surname, setSurname] = useState('Qəhrəmanov');

  // 4. Səhifə başlığını yeniləmək üçün effekt istifadə edin
  useEffect(function updateTitle() {
    document.title = name + ' ' + surname;
  });

  // ...
}

React hansı state-in hansı useState çağırışına aid olduğunu haradan bilir? React, Hookların çağırış sırasına etibar edir. Bizim nümunədə, Hook çağırışlarının sırası hər render zamanı eyni qalır:

// ------------
// İlk render
// ------------
useState('Abbas')          // 1. "name" state dəyişənini 'Abbas' ilə inisializasiya edin
useEffect(persistForm)     // 2. Anketi qorumaq effekt əlavə edin
useState('Qəhrəmanov')     // 3. "surname" state dəyişənini 'Qəhrəmanov' ilə inisializasiya edin
useEffect(updateTitle)     // 4. Səhifə başlığını yeniləmək üçün effekt əlavə edin

// -------------
// Second render
// -------------
useState('Abbas')          // 1. "name" state dəyişənini oxuyun (arqument artıq işlədilmir)
useEffect(persistForm)     // 2. Anketi qoruyan effekti əvəz edin
useState('Qəhrəmanov')     // 3. "surname" state dəyişənini oxuyun (arqument artıq işlədilmir)
useEffect(updateTitle)     // 4. Səhifə başlığını yeniləmək üçün effekti əvəz edin

// ...

Hook çağırışlarının sırasının eyni qaldığından React, eyni state-i lokal dəyişənə təyin edə bilir. Hook çağırışını şərtin daxilində yazdıqda nə baş verir (məsələn, persistForm effekti)?

  // 🔴 Hooku şərt daxilində işlədərək birinci qaydanı pozuruq
  if (name !== '') {
    useEffect(function persistForm() {
      localStorage.setItem('formData', name);
    });
  }

İlk render üçün name !== '' şərti true-a bərabər olduğundan biz bu Hooku çağırırıq. Lakin, istifadəçi anket sahəsini sildikdə sonrakı render zamanı verilən şərt false-a bərabər olur. İndi, render zamanı Hooku atladığımızdan Hook çağırışlarının sırası dəyişir:

useState('Abbas')           // 1. "name" state dəyişənini oxuyun (arqument artıq işlədilmir)
// useEffect(persistForm)   // 🔴 Hook atlandı!
useState('Qəhrəmanov')      // 🔴 2 (3 yox). "surname" state dəyişəni oxunmadı
useEffect(updateTitle)      // 🔴 3 (4 yox). Effekt əvəz olunmadı

React, useState Hook çağırışından nə qaytarılacağını bilmir. React, əvvəlki render zamanı olduğu kimi ikinci Hookun persistForm effektinə uyğun gəldiyini gözləyir. Bu nöqtədən sonra atlanan Hookdan sonra gələn Hookların sırası bir növbə arxaya gedəcək. Bu, baqlara səbəb olacaq.

Bu səbəbdən Hooklar komponentlərin yuxarısında çağrılmalıdır. Əgər effekti şərti çağırmaq istəyiriksə, bu şərti, Hookun daxilinə əlavə etməliyik:

  useEffect(function persistForm() {
    // 👍 Birinci qaydanı pozmuruq
    if (name !== '') {
      localStorage.setItem('formData', name);
    }
  });

Nəzərə alın ki, təmin olunan lint qaydasını işlətdikdə bu problem linter xətası qaytaracaq və sizə bu haqqda fikirləşməməyə imkan yaradacaq. Buna baxmayaraq, indi Hookların niyə belə işlədiyini bilirsiniz.

Sonrakı Addımlar

Biz indi xüsusi Hookların yazılmasını öyrənə bilərik! Xüsusi Hooklar ilə React-in təmin etdiyi Hookları bir yerə yığıb öz abstraksiyanızı yarada bilər və fərqli komponentlər arasında işlənən eyni state-li məntiqi paylaşa bilərsiniz.