Как стать автором
Обновить

Про реакт обзорно

Уровень сложностиПростой

Дисклеймер: данная статья ставит задачу познакомить читателя с библиотекой React, ее отличиях от ванильной верстки статических страниц, а так же с основными концепциями, на которых основана работа данной библиотеки. Автор статьи будет рассматривать данную технологию в абстракции и, возможно, в отрыве от реальных процессов, происходящих внутри React-приложения: в статье не будет рассматриваться Fiber, классовый подход и остальные технические вещи, которые лишь послужат отвлечением от основной сути. Статья представляет собой милкшейк из моего личного практического опыта, личных наблюдений, теории из официальной документации React.dev, а также информации, взятой со статей на Reddit и прочих ресурсах.

Небольшое оглавление:

1. Что такое React?

2. Отличия React от ванильных html/css/js

3. Внутрянка React-приложения

4. Минусы использования

5. Некоторые итоги

Что такое React?

Следует начать с прямого определения того, чем является данная технология. React - это библиотека, которая берет за основу такой язык программирования как js (либо ts) а так же имеет свой собственный "язык" - JSX (который на самом деле не является языком, об этом позже) и которая позволяет создавать динамичные, высокопроизводительные пользовательские интерфейсы как в браузерах, так и нативно на мобильных устройствах (благодаря технологии React Native).

Многие часто ошибочно утверждают, что данная библиотека является фреймворком, однако это не так, React - это библиотека, которая имеет некоторые схожести с фреймворком по типу Angular, и я специально акцентирую на этом внимание, чтобы повысить техническую грамотность обозревателя.

Отличия React от ванильных html/css/js

Если вам удосуживалось когда-либо верстать сайты-визитки или лендинги, то вы, наверняка, знакомы с устройством статических веб-страниц: скелет-разметка сайта, написанная на html, внешнее оформление этого скелета в виде стилей css, а так же оживление этого сайта путем javascript. В данном случае React всего лишь несколько изменяет данный процесс: вместо отдельного написания сначала разметки, затем стилизации отдельных классовых html элементов и придачи им динамики при помощи ванильного Javascript, React позволяет централизованно и параллельно создавать ту же разметку, задавать ей внешнее представление и придавать ей живности в рамках одного-двух файлов.

И тут важно слегка освежить знания о том, как страницу парсит и отображает клиентский браузер, напомню, как он это делает в случае, если мы сверстали классическую статическую страницу:

1) Сначала браузер клиента получает все необходимые для работы файлы: html, css, javascript.

2) Браузер начинает построение разметки сайта, он анализирует html код и помещает в DOM все элементы в нужном порядке.

3) Затем браузер сопоставляет элементам их стили.

4) Далее браузер вешает прослушиватели событий (event listeners на элементы, если у них таковые имеются)

Кстати, возможно, вы замечали, что при первичной загрузке страницы, даже если все элементы успешно отобразились, и казалось бы, что со страницей уже можно работать, вы нажимали кнопки и они никак не реагировали, скорее всего вы пытались взаимодействовать с ними в тот момент, когда браузер еще не успел навесить на элементы прослушиватели.

5) Сайт отобразился полностью и готов к работе.

Так выглядит генерация страницы при классическом методе верстки страниц.

В случае с React данная схема выглядит немного иначе:

1) В браузер клиента все так же приходят необходимые файлы для работы, но в данном случае ими являются заранее скомпилированные javascript файлы, которые в этот же момент начинают свой рантайм при попадании в браузер.

Минимизированный js файл, приходящий в браузер
Минимизированный js файл, приходящий в браузер

2) При помощи этих скриптов строится DOM страницы, элементам даются стили, параллельно React-приложение строит свое собственное Virtual DOM-дерево, которое понадобится ему для ререндера компонентов. По тому же Virtual DOM React генерирует реальный DOM и вставляет его в HTML-документ, обычно в элемент с id="root".

"Пустое" React-приложение, в котором имеется только root-элемент.
"Пустое" React-приложение, в котором имеется только root-элемент.

3) Затем происходит так называемая "гидрация" компонентов, по сути, то же навешивание слушателей событий.

4) React-приложение готово к работе.

Кстати в данной схеме я описал CSR (Client-Side-Rendering), когда сайт генерируется на стороне клиента, а не на сервере (SSR) (Возможно, этому будет посвящена статья)

Из данного сравнения видны отличия сайтов, написанных традиционным методом и при помощи React.

Следующие особенности React можно отнести к его отличиям а так же к его плюсам:

1) Компонентный подход: вместо написания единой html разметки мы создаем "кирпичи" - компоненты, которыми можно строить разметку приложения и эффективно переиспользовать, что существенно помогает соблюдать принцип DRY. Таким образом компонент инкапсулирует в себе разметку, стилизацию и логику, что очень удобно.

2) Из первой особенности вытекает уменьшение общего количества кода проекта, так как мы сокращаем html бойлерплейт (в свою очередь React требует свой собственный бойлерплейт и при помощи некоторых сборщиков и пакетов имеет свой скаффолдинг).

3) Одна из важнейших вещей компонентного подхода, который позволяет осуществить React, является управление состояниями компонентов, которые как раз придают этим компонентам динамику и интерактивность. Хранение состояний и управление ими в рамках компонентов реализуется с помощью так называемых хуков.

4) React-приложение генерируется на клиенте значительно быстрее, чем ванильно-реализованная страница, это достигается за счет того, что React-приложение создается из тех самых заранее скомплированных и минимизированных js скриптов, получаемых браузером. В добавок Virtual DOM реакта позволяет сократить количество операций над реальным DOM (в этом ему так же помогает движок Fiber, который находится в его ядре)

Внутрянка React

С отличиями разобрались, теперь нужно пронаблюдать, как устроен проект, написанный при помощи React, и в качестве примера я возьму последний свой небольшой проект. Я пройдусь по верхним файлам и объясню, для чего служит каждый, а затем мы углубимся в иерархии и познакомимся, непосредственно, с внутрянкой React.

Структура проекта
Структура проекта
  1. .vscode - папка конфигурации настроек IDE, в котором ведется разработка, никак не связан с React.

  2. node_modules - папка, которая содержит в себе пакеты, необходимые для работы всего, важно упомянуть, что данную папку необходимо помещать в .gitignore, чтобы не захламлять удаленный репозиторий (к тому же если вес данной папки достаточно высок, то запушить файлы в репозиторий может даже не получиться)

  3. package.json - файл конфигурации проекта (его название, версия, некоторые другие метаданные, конфигурация алиасов для дев скриптов, внутренние зависимости и тд)

  4. package-lock.json - хранит историю зависимостей в проекте.

  5. vite.config.js - конфиг сборщика проекта, который позволяет собирать код React и запускать приложение. В качестве сборщика в проекте использован Vite, так же существуют такие сборщики как Webpack, CRA (устарел)

  6. .eslintrc.cjs - линтер, который помогает писать код в соответствии стандартам ES6 и подсвечивает ошибки. При грамотной настройке позволяет делать автофиксы после сохранения изменений в файле.

А теперь коснемся тех файлов, находящихся в папке src, которые служат точкой входа в React-приложение:

  1. index.html - файл первоначальной разметки, в которой содержится рутовый элемент, в который React вставит разметку после вычислений в Virtual DOM.

  2. main.jsx - скрипт, который рендерит приложение внутрь root-элемента:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

3. App.jsx - первый компонент React-приложения, который содержит в себе все остальные компоненты:

const App = () => {
  return <h1>Hello World</h1>
}

export default App

А вот как выглядит компонент, имеющий дочерние компоненты:

import CardButton from ' .. /CardButton/CardButton';
import styles from './JournalAddButton.module.css';

const JournalAddButton = () => {
  return (
  <CardButton className={styles['journal-add']}>
    <img src="/plus-icon.svg" alt="" />
    Новая заметка
  </CardButton>
  );
};

export default JournalAddButton;

Прошу обратить внимание на данный блок кода:

import React from 'react'; // Импорируется React, из которого берется метод createElement
import './App.css';

function App() {

  return React.createElement('div', {},
    React.createElement('h1', {}, 'Текст заголовка тэra h1'),
    React.createElement('h1', {}, 'Текст заголовка тэrа h1'),
    React.createElement('h1', {}, 'Текст заголовка тэга h1'),
  ); // JSX - это синтаксический сахар для вот такого рода функции, возвращает html элемент
     // createElement не может вернуть tuple из двух и более объектов

    // То же самое но только на JSX:
  return (
    <React.Fragment>
      <div>
      <h1>Текст заголовка тэга h1</h1>
      <h1>Текст заголовка тэга h1</h1>
      <h1>Тест заголовка тэга h1</h1>
      </div>
    </React.Fragment>
    );
};

export default App;

Из данного блока кода можно понять, что JSX - это все таки не язык, а синтаксический сахар - обертка над реальным кодом, который выполняет React при рендеринге компонента. Если в компоненте имеются вложенные компоненты, то он выполняет ту же самую процедуру, тем самым вкладывая функции сreateElement одну в другую, что очень быстро превращается в нечитаемую матрешку.

А теперь небольшой цикл работы React:

1) Реакт находит самый верхний компонент-родитель, запускает его функцию, и поэтапно вызывает соответствующие функции дочерних компонентов, параллельно строя свой Virtual DOM.
2) Когда реакт построил свое дерево, он создает реальное DOM дерево и помещает его в документ. (вмонтирование)
3) Если в каком-нибудь компоненте случились изменения (пользователь куда-нибудь кликнул), или какой-либо компонент вообще удалился, React сравнивает новое и предыдущее деревья, находит в них отличающиеся элементы и минимально обновляет реальный DOM, применяя только те изменения, которые были найдены на этапе сравнения (патчинг)

Вот так в упрощенном виде выглядит рендеринг в React-приложении.

Как работает цикл ререндера в реакт приложении - уже детали технической реализации, я не преследую цели нагрузить читателя, поэтому опускаю этот момент (до следующей статьи, возможно).

Минусы использования React

Вскользь упомяну недочеты библиотеки и почему иногда следует обратить внимание все-таки на какие-то другие способы реализации веб-приложения.

1) React - это библиотека, а не полноценный фреймворк. При разработке в проект приходится интегрировать дополнительные библиотеки для решения таких задач, как маршрутизация, управление глобальными состояниями и обработка побочных эффектов. Это добавляет сложность в первоначальной настройке и архитектуре приложения.

2) Сложности с SEO: по умолчанию react-приложение рендерится на стороне клиента, что может затруднять индексацию страниц поисковыми системами. Это может потребовать настройки серверного рендеринга (например с этим справляется Next.js) для улучшения SEO.

3) Хоть это в общем распространяется на весь фронтэнд, но в плоскости реакта эта проблема становится более явной - отсутствие единых стандартов реализации. В реакте очень много способов решить одну и ту же проблему, и очень часто сложно найти единственно правильный, таким образом это затрудняет разработку и обучение в целом.

Некоторые итоги

Я не затронул еще очень много тонкостей и моментов, моя цель была обзорно показать, что из себя представляет React и в каких местах он соприкасается с традиционными методами верстки. Если вам понравилась данная статья, то можете оставить обратный отзыв, указать на ошибки, поделиться с теми, кого может заинтересовать данная тема.

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.