Kodun Icmalı

Bu bölmədə React kodunun orqanizasiyası, konvensiyaları və tətbiqinin icmalı göstərilir.

Əgər React-ə töhvə vermək istəyirsinizsə, buradakı təlimatların sizə dəyişiklik etməkdən qorxmayacağınıza imkan yaradacağına ümid edirik.

Burada göstərilən konvensiyaların React applikasiyalarında işlədilməsini tövsiyyə etmirik. Bu konvensiyaların çoxu tarixi səbəblərə görə mövcuddur və zaman keçdikcə bu konvensiyalar dəyişə bilər.

Xarici Asılılıqlar

React-in heç bir xarici asılılığı yoxdur. Adətən, require() çağırışları React-in kodunda olan fayllara istinad edir. Lakin, burada bir neçə nadir istisnalar var.

fbjs repo-sunun mövcud olmasının səbəbi React-in bəzi faydalı funksiyaları Relay kimi kitabxanalar ilə paylaşmasıdır. Biz bu funksiyaları həmişə sinxron saxlayırıq. Biz Node ekosistemində olan bu faydalı funksiyaların ekvivalenti olan modullardan istifadə etmirik. Çünki, biz Facebook mühəndislərinin istənilən zaman dəyişikliklər edə bilməsini istəyirik. fbjs-də olan heç bir funksiya açıq API kimi qəbul olunmur. Bu API-lar yalnız Facebook-un React kimi layihələrində işlənilir.

Ana Direktoriyalar

React repo-sunu klon etdikdə aşağıdakı direktoriyaları görəcəksiniz:

  • packages direktoriyasında React reposunda olan bütün paketlərin metadata-ları (package.json kimi) və mənbə kodları (src alt direktoriyalarında) saxlanılır. Əgər etdiyiniz dəyişiklik kod ilə əlaqəlidirsə, siz vaxtınızın çoxunu hər paketin src alt direktoriyasında keçirəcəksiniz.
  • fixtures direktoriyasında iştirakçılar üçün test React applikasiyaları saxlanılır.
  • build direktoriyasında React-in qurulma nəticəsini saxlanılır. Bu direktoriya repo-da yoxdur, amma bu direktoriyanı React-i ilk dəfə quraşdırdıqda görəcəksiniz.

Sənədlər React-dən kənar repo-da saxlanılır.

Bu repo-da digər ana direktoriyalar da var. Lakin, bu direktoriyalarda alətlər saxlanılır və adətən iştirak etdiyiniz zaman bu direktoriyalarda dəyişiklik etməyəcəksiniz.

Testlərin Yerləşdirilməsi

Bizdə vahid testləri üçün ana direktoriya yoxdur. Əvəzinə, testlər test olunan faylların olduğu direktoriyada olan __tests__ direktoriyasında saxlanılır.

Məsələn, setInnerHTML.js faylı üçün testlər __tests__/setInnerHTML-test.js faylında yerləşir.

Xəbərdarlıq və İnvariantlar

React kodunda xəbərdarlıqları göstərmək üçün warning modulundan istifadə edilir:

var warning = require('warning');

warning(
  2 + 2 === 4,
  'Riyaziyyat bu gün işləmir.'
);

Xəbərdarlıqlar warning şərti false olduqda göstərilir.

Burada şərtlər, istisna vəziyyətlər əvəzinə normal vəziyyətləri əks etdirməlidir.

Konsola dublikat xəbərdarlıqları göstərməkdən çəkinməyə çalışın:

var warning = require('warning');

var didWarnAboutMath = false;
if (!didWarnAboutMath) {
  warning(
    2 + 2 === 4,
    'Riyaziyyat bu gün işləmir.'
  );
  didWarnAboutMath = true;
}

Xəbərdarlıqlar yalnız təkmilləşmə zamanı aktivdirlər. Produksiya zamanı xəbərdarlıqlar qurulan paketdən silinir. Əgər hər hansı kodun icrasını saxlamaq istəyirsinizsə, invariant modulundan istifadə edin:

var invariant = require('invariant');

invariant(
  2 + 2 === 4,
  'Giriş qadağandır!'
);

İnvariant invariant şərti false olduqda göstərilir.

“Invariant”, “bu şərtin həmişə true olması” deməkdir. Bunun iddia etməyə (assertion) bənzədiyini fikirləşə bilərsiniz.

Təkmilləşmə və produksiya davranışlarının eyni saxlanması vacibdir. Bu səbəbdən, invariant-lar hər iki mühitdə göstərilir. Produksiya zamanı paket ölçüsünü azaltmaq üçün xəta mesajları avtomatik olaraq xəta kodları ilə əvəz edilir.

Təkmilləşmə və Produksiya

Kod bloklarının yalnız təkmilləşmə zamanı mövcud olması üçün __DEV__ pseudo-qlobal dəyişənindən istifadə edin.

Bu dəyişən, kompilyasiya zamanı eyni-sətrə keçirilir və CommonJS qurulması zamanı process.env.NODE_ENV !== 'production' formalı kod ilə əvəz olunur.

Bu dəyişən, bağımsız qurulmalar üçün minifikasiya olunmamış qurulmalarda true-a çevrilir. Minifikasiya olunmuş qurulmalarda isə dəyişəni saxlayan if bloku ilə birlikdə tam silinir.

if (__DEV__) {
  // Bu blokdakı kod yalnız təkmilləşmə zamanı mövcud olacaq.
}

Flow

Bu yaxınlarda biz koda Flow yoxlamalarını əlavə etdik. Lisenziya başlıq kommentində @flow ilə işarələnən fayllarda tip yoxlamaları baş verəcək.

Biz mövcud koda Flow işarələrinin əlavə edilmələrinin PR-larını qəbul edirik. Flow işarələri aşağıdakı formada olur:

ReactRef.detachRefs = function(
  instance: ReactInstance,
  element: ReactElement | string | number | null | false,
): void {
  // ...
}

Mümkün olduğu zaman yeni kodlarda Flow işarələri olmalıdır. Kodunuzu lokal mühitdə Flow ilə yoxlamaq üçün yarn flow əmrini icra edə bilərsiniz.

Dinamik İnyeksiya

React bəzi modullarda dinamik inyeksiyadan istifadə edir. Bunun həmişə açıq olmasına baxmayaraq bu, kodun anlaşılmasını azaldır. Bunun mövcud olmasının əsas səbəbi React-in əvəllər yalnız DOM-u dəstəkləməsindən gəlir. React Native, React-in forku kimi başlanılıb. Biz, React Native-in bəzi davranışları əvəzləməsi üçün dinamik inyeksiyadan istifadə etdik.

Siz, bəzi modulların dinamik asılılıqlarının aşağıdakı formada təyin edildiyini görəcəksiniz:

// Dinamik inyeksiya olunub
var textComponentClass = null;

// Dinamik inyeksiya olunan dəyərdən asılıdır
function createInstanceForText(text) {
  return new textComponentClass(text);
}

var ReactHostComponent = {
  createInstanceForText,

  // Dinamik inyeksiya üçün fürsət yaradır
  injection: {
    injectTextComponentClass: function(componentClass) {
      textComponentClass = componentClass;
    },
  },
};

module.exports = ReactHostComponent;

injection sahəsi xüsusi formada idarə olunmur. Lakin, konvensiyaya görə modulun icra zamanı bəzi asılılıqların (adətən, platformaya xas) inyeksiya ediləcəyi bilinir.

Kodda bir neçə inyeksiya nöqtələri var. Gələcəkdə, biz dinamik inyeksiya mexanizmindən imtina etmək və bütün hissələri statik şəkildə qurmaq istəyirik.

Çoxlu Paketlər

React, monorepo-dur. Bu repo bir neçə paketdən ibarətdir. Bu paketlər eyni zamanda koordinasiya oluna bilir və bütün paketlərin issue-ları bir yerdə saxlanılır.

React Core

React-in “core”-unda bütün yuxarı səviyyəli React API-ları saxlanılır. Məsələn:

  • React.createElement()
  • React.Component
  • React.Children

React core-da yalnız komponentləri təyin etmək üçün lazım olan API-lar saxlanılır. Burada rekonsilyasiya alqoritmi və ya digər platformaya xas olan kodlar mövcud deyil. Buradakı kodlar həm React DOM, həm də React Native komponentləri tərəfindən istifadə edilir.

React core-un kodu packages/react direktoriyasında saxlanılır. React core, NPM-də react paketi adı altında mövcuddur. Bağımsız brauzer qurulmaları isə react.js adlanır. Bu qurulmalarda ixrac edilən qlobal dəyişənin adı React-dir.

Render Edici Qurğular

Başlanğıcda React yalnız DOM üçün yaradılmışdı, amma bir zaman sonra React Native ilə nativ platformalar da dəstəklənməyə başlandı. Bu adaptasiya nəticəsində React daxilinə “render edici qurğular” konsepsiyası təqdim olundu.

Render edici qurğular React ağacını platformaya xas olan çağırışlara çevirmək üçündür.

Render edici qurğular packages/ direktoriyasında yerləşir:

Rəsmi dəstəklənən render edici qurğularından biri də react-art-dır. Əvvəllər bu qurğu ayrı GitHub repo-sunda idi, amma hələlik biz bu qurğunu əsas kod repo-suna əlavə etmişik.

Qeyd:

Texniki olaraq react-native-renderer qurğusu React-in React Native tətbiqi ilə işləməsi üçün çox nazik bir təbəqədir. Nativ görünüşləri idarə edən, platformaya xas olan kodlar və bu kodların işləməsi üçün lazım olan komponentlər React Native repo-sunda saxlanılır.

Rekonsilyatorlar

React DOM və React Native kimi çox fərqlənən render edici qurğular belə öz aralarında məntiqlər paylaşırlar. Xüsusilə, deklarativ render etmə, xüsusi komponentlər, state, lifecycle metodları və ref-lərin bütün platformalarda düzgün və stabil işləməsi üçün rekonsilyasiya alqoritmi eyni qalmalıdır.

Bunu həll etmək üçün fərqli render edici qurğular öz aralarında bəzi kodları paylaşırlar. Biz React-in bu hissəsini “rekonsilyator” və “rekonsilyasiya edici qurğu” adlandırırıq. setState kimi yenilik planlaşdırıldıqda rekonsilyator ağacda olan komponentlərin render() funksiyalarını çağıraraq bu komponentləri mount edir, yeniləyir və unmount edir.

Rekonsilyatorların açıq API-ları olmadığından bu qurğular üçün paketlər mövcud deyil. Əvəzinə, bu qurğular yalnız React DOM və React Native kimi render edici qurğular tərəfindən istifadə edilir.

Stack Rekonsilyatoru

React 15 və əvvəlki buraxılışlarda “stack” rekonsilyatoru işlədilirdi. Biz bu qurğudan istifadə etməyi dayandırmışıq. Lakin, bu qurğu haqqında detallı məlumat almaq üçün sonrakı bölməyə baxın.

Fiber Rekonsilyatoru

Stack rekonsilyatorunda olan problemləri və ümumilikdə uzun müddət mövcud olan problemləri həll etmək üçün göstərdiyimiz cəhdlərdən biri “fiber” rekonsilyatorudur. Bu qurğu React 16-dan başlayaraq standart rekonsilyator kimi işlədilir.

Bu qurğunun əsas məqsədləri aşağıda göstərilib:

  • Kəsilə bilən işlərin kiçik hissələrə parçalanması.
  • Proqresdə olan işlərin prioritetləşdirilməsi, rebeyzi və yenidən istifadə edilə bilməsi.
  • React-də şablonu dəstəkləmək üçün valideyn və uşaqlar arasında istehsalın növbələnməsi.
  • render()-dən bir neçə elementin qaytarılması.
  • Xəta sərhədləri üçün daha yaxşı dəstək.

React-in Fiber Arxitekturası haqqında əlavə məlumat almaq üçün burabura baxın. Bu rekonsilyatorun React 16-da olmasına baxmayaraq hələki asinxron xüsusiyyətlər standart şəkildə aktivləşməyib.

React rekonsilyatoru packages/react-reconciler direktoriyasında saxlanılır.

Hadisə Sistemi

React, render edici qurğulardan asılı olmayan, React DOM və React Native-də işləyən sintetik hadisə sistemi tətbiq edir. Bu sistemin kodu packages/legacy-events direktoriyasında saxlanılır.

Əgər maraqlanırsınızsa, hadisə sistemini dərindən başa salan videoya (66 dəq) baxa bilərsiniz.

Sonrakı Addımlar

React 16-dan öncə mövcud olan rekonsilyasiya edici qurğunun tətbiqi haqqında dərindən məlumat almaq üçün sonrakı bölməyə baxın. Biz hələki, yeni rekonsilyasiya edici qurğunun daxilini sənədləşdirməmişik.