
Дисклеймер: данная статья ставит задачу познакомить читателя с библиотекой 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 файлы, которые в этот же момент начинают свой рантайм при попадании в браузер.

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

.vscode - папка конфигурации настроек IDE, в котором ведется разработка, никак не связан с React.
node_modules - папка, которая содержит в себе пакеты, необходимые для работы всего, важно упомянуть, что данную папку необходимо помещать в .gitignore, чтобы не захламлять удаленный репозиторий (к тому же если вес данной папки достаточно высок, то запушить файлы в репозиторий может даже не получиться)
package.json - файл конфигурации проекта (его название, версия, некоторые другие метаданные, конфигурация алиасов для дев скриптов, внутренние зависимости и тд)
package-lock.json - хранит историю зависимостей в проекте.
vite.config.js - конфиг сборщика проекта, который позволяет собирать код React и запускать приложение. В качестве сборщика в проекте использован Vite, так же существуют такие сборщики как Webpack, CRA (устарел)
.eslintrc.cjs - линтер, который помогает писать код в соответствии стандартам ES6 и подсвечивает ошибки. При грамотной настройке позволяет делать автофиксы после сохранения изменений в файле.
А теперь коснемся тех файлов, находящихся в папке src, которые служат точкой входа в React-приложение:
index.html - файл первоначальной разметки, в которой содержится рутовый элемент, в который React вставит разметку после вычислений в Virtual DOM.
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 и в каких местах он соприкасается с традиционными методами верстки. Если вам понравилась данная статья, то можете оставить обратный отзыв, указать на ошибки, поделиться с теми, кого может заинтересовать данная тема.