Як працює React під капотом

React - це дуже популярна бібліотека JavaScript. З більш ніж 5,5 мільйонами завантажень щотижня, React користується великою популярністю. Але не багато розробників React знають, як React працює під капотом.

У цьому дописі я спробую розкрити кілька цікавих речей про React, які, як розробник React, можуть вас зацікавити. Почнемо спочатку.

Але перед тим, як ми почнемо, якщо ви розробник React, я маю для вас цікаві новини! Після того, як ви закінчите цю статтю, ви зможете розробити щось круте з React і вигравати призи по дорозі :)

Що робить React?

По суті, React в основному підтримує дерево для вас. Це дерево може виконувати ефективні обчислення різниць на вузлах.

Подумайте про свій HTML-код як про дерево. Насправді саме так браузер обробляє вашу DOM (ваш відтворений HTML у браузері). React дозволяє ефективно реконструювати свій DOM в JavaScript і надсилати лише ті зміни до DOM, які відбулись насправді.

JSX - це синтаксичний цукор

Немає нічого подібного до JSX - ні в JavaScript, ні в браузері. JSX - це просто синтаксичний цукор для створення дуже специфічних об’єктів JavaScript.

Коли ви пишете щось на зразок:

const tag = 

Hello

що ви по суті робите це:

const tag = React.createElement("h1", {}, "Hello")

Розумієте, коли ви починаєте писати вкладені матеріали, це не тільки важко кодувати, але також стає дуже незручно підтримувати таку кодову базу. Таким чином, JSX допомагає вам довести чистоту HTML до потужності JavaScript.

Але що робить React.createElement сам? Він створює звичайний старий об'єкт JavaScript. Насправді ви можете зателефонувати вручну і переконатися в цьому самі!

Розумієте, у нас такий об’єкт:

{ $$typeof: Symbol(react.element), key: null, props: {children: "Hello"}, ref: null, type: "div" }

І якщо ми почнемо вкладати елементи так:

React.createElement('div', { }, React.createElement('p', {}, 'A p inside a div') ) 

Ми б почали отримувати вкладені об'єкти:

Отже, тепер ви знаєте, як тільки все JSX буде проаналізовано і всі виклики React.createElement будуть вирішені, ми потрапляємо до одного гігантського вкладеного об’єкта, як вище.

React Renderer

Тепер, якщо ви повернетесь до точки, з якої ми запускаємо наш додаток, ви побачите, що у вашому файлі index.js ви знайдете такий рядок:

// .. prev code ReactDOM.render(, container)

Зверху ми знаємо, що після закінчення синтаксичного аналізу це просто величезний об’єкт елементів React. Тоді як React здатний створювати з нього фактичні div і p теги? Зустріньте ReactDOM.

ReactDOM, у свою чергу, рекурсивно створює вузли залежно від їх властивості 'type' і додає їх нарешті до DOM.

На цьому етапі повинно бути зрозуміло, чому від'єднання React від рендерів насправді є чудовим кроком! Що React робить, це просто побудувати дерево інтерфейсу користувача, яке можна було б використовувати не тільки в Інтернеті, але і в таких середовищах, як мобільне, з огляду на те, що доступний візуалізатор, який може спілкуватися з основною ОС. Тут React Native приходить пограти. Розумієте, React Native використовує бібліотеку React, але не ReactDOM як візуалізацію. Натомість сам пакет response-native є візуалістом.

Ми робимо це в рідному додатку з реакцією, щоб запустити додаток:

const { AppRegistry } = require('react-native') AppRegistry.registerComponent('app', () => MainComponent)

Дивись! Немає ReactDOM. Чому ні? Оскільки ми не маємо таких методів, як appendChild, ми також не маємо середовища, подібного до DOM. Натомість для мобільних телефонів нам потрібна підтримка інтерфейсу користувача безпосередньо з ОС. Але бібліотеці React цього не потрібно знати, про це дбає візуалізатор (React Native).

Реагуйте на примирення

Коли ми говоримо, що React підтримує копію DOM, використовуючи віртуальний DOM в JavaScript, і використовує його для будь-яких змін і застосовує до реального DOM, ми не хочемо, щоб React грубо форсував свій шлях. Реагуйте, насправді робить дуже ліниве примирення. React зробить найменшу кількість змін, тобто намагатиметься повторно використовувати елементи, атрибути і навіть стилі, якщо це можливо!

Розглянемо цей приклад:

stuff

Скажімо, ви змінили цей вираз JSX на наведений нижче, використовуючи якусь умову або якийсь стан:

something else

Тепер, коли різняться, React це добре побачить, тег img використовує одне і те ж className як у старих, так і в нових деревах, так навіщо його змінювати. І це просто змінить ваш атрибут alt і рухається далі.

Однак є і загвоздка. Оскільки ми не хочемо, щоб React робив багато обчислень на різну частину, React вважав би, що якщо батько змінився, його піддерево, що містить, точно змінилося. Наприклад:

I did not change

Якщо ви зміните цей JSX на наступний за допомогою умови / стану:

I did not change

Хоча ви могли бачити, що нам не потрібно відтворювати внутрішній тег p, але React не може знати, що під час обходу дерева зверху (якщо, звичайно, ви не виконуєте важкі різниці дерев, що є набагато дорожчими алгоритмами, ніж евристична реакція O (n) слід для різниці). Отже, React вирішує знищити всіх дітей (тобто викликати їх функції очищення в useEffect, або componentWillUnmount у компонентах, що базуються на класах) і заново створити дітей з нуля.

Ключі для реагування

Додаючи / видаляючи елементи у вузлі, React просто циклічно перемикається на дітей у старому дереві та дітей у новому дереві вузла та позначає місця, де йому потрібно виконати будь-яке додавання / видалення. Але це має недолік без додаткової допомоги розробника. Розглянемо цей приклад:

  • A
  • B

Подумайте, що це змінено на наступне за умовою / станом:

  • Z
  • A
  • B

Тепер, коли React почне порівнювати два списки для різниці, він знайде різницю в дочірньому вузлі 1, змінить старий A на новий Z, потім знову на дочірньому вузлі 2, змінить його зі старого B на новий A, а потім остаточно додати новий вузол B.

Однак кращим способом було б зберегти існуючі вузли A і B і просто додати вузол Z. Але як React може про це знати? Клавіші React допомогли б.

Клавіші просто забезпечують приємний спосіб реагувати, щоб дізнатись, які елементи змінювались чи не змінювались при різниці. Тепер, замість порівняння цілого елемента, React порівняє ключі дочірніх елементів, щоб побачити, який елемент потрібно додати / видалити. Наведений нижче спосіб - це ефективний спосіб виконати те саме:

  • A
  • B

Тепер, якщо це буде змінено на:

  • Z
  • A
  • B

React тепер буде знати, що клавіші 'A' і 'B' вже існують, тому нам просто потрібно додати новий елемент з клавішею 'Z'.

Ви розробник React? Продемонструйте свої навички React , розробивши 3-хвилинну інтерактивну гру в React і виграйте толстовки, сорочки та кружки для кави ! Візьміть участь в codecomp шляхом приєднання розбрати сервера codedamn в тут

Отже, це були деякі важливі концепції, які, на мою думку, були б дуже корисними для вас як розробників React, щоб ви почали розуміти суть React і те, як це насправді працює. Не соромтеся передавати будь-які пропозиції чи запитання, які у вас є про те саме.

Ви можете стежити за мною у твіттері, щоб дізнатись більше про твіти та інше щодо JS / кодування. Мир!