Основы веб-разработки на ReactJS

Интенсивный курс по созданию современных одностраничных приложений (SPA) с использованием библиотеки React. Вы пройдете путь от понимания JSX и компонентов до управления состоянием и взаимодействия с внешними API.

1. Введение в экосистему React: JSX, компоненты и пропсы

Введение в экосистему React: JSX, компоненты и пропсы

Добро пожаловать в курс «Основы веб-разработки на ReactJS». Это первая статья, и мы начнем с фундамента, на котором строится вся современная frontend-разработка. Если вы уже знакомы с HTML, CSS и JavaScript, то React станет для вас следующим логическим шагом, который превратит верстку статических страниц в создание динамических приложений.

Что такое React и почему он так популярен?

React — это JavaScript-библиотека для создания пользовательских интерфейсов, разработанная компанией Facebook (ныне Meta). Впервые она была представлена в 2013 году и с тех пор кардинально изменила подход к веб-разработке.

Главная особенность React заключается в том, что он декларативен. В традиционном (императивном) программировании на jQuery или ванильном JS вы часто говорите браузеру, как изменить интерфейс: «найди этот элемент, удали у него класс, добавь текст». В React вы просто описываете, как должен выглядеть интерфейс в зависимости от текущего состояния данных, а React сам решает, как наиболее эффективно обновить DOM (Document Object Model).

> React делает создание интерактивных интерфейсов безболезненным. Создавайте простые представления для каждого состояния вашего приложения, и React будет эффективно обновлять и рендерить только нужные компоненты при изменении данных. Официальная документация React

Ключевые преимущества:

  • Компонентный подход: Интерфейс разбивается на независимые части.
  • Однонаправленный поток данных: Данные текут сверху вниз, что делает приложение предсказуемым.
  • Экосистема: Огромное сообщество, тысячи готовых библиотек и инструментов.
  • Компонентный подход

    Представьте, что вы строите дом из конструктора LEGO. У вас есть кирпичики разного размера, цвета и формы. Вы можете собрать из них стену, из стен — комнату, а из комнат — целый дом. В React всё работает точно так же.

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

    !Визуализация того, как страница разбивается на иерархию вложенных компонентов.

    Такой подход позволяет: * Переиспользовать код: Создав кнопку один раз, вы можете использовать её везде. * Упростить тестирование: Легче проверить работу одной кнопки, чем всего сайта сразу. * Разделить ответственность: Каждый компонент занят своим делом.

    JSX: Синтаксический сахар или магия?

    Когда вы впервые видите код на React, он может показаться странным. Вы увидите HTML-теги прямо внутри JavaScript-кода. Этот синтаксис называется JSX (JavaScript XML).

    Пример JSX:

    На первый взгляд это выглядит как HTML, но это не он. Браузеры не понимают JSX. Перед тем как код попадет в браузер, специальные инструменты (например, Babel) трансформируют его в обычный JavaScript.

    Что происходит «под капотом»?

    JSX — это просто красивый способ написать вызов функции React.createElement(). Посмотрите на разницу:

    Как пишем мы (JSX):

    Во что это превращается (JavaScript):

    Очевидно, что писать на JSX намного удобнее и привычнее для верстальщиков.

    Правила написания JSX

    Чтобы JSX работал корректно, нужно соблюдать несколько строгих правил:

  • Один родительский элемент: Вы не можете вернуть два соседних тега без обертки. Всё должно быть обернуто в один общий тег или во фрагмент.
  • Неправильно:

    Правильно:

    Или используя React Fragment (пустые скобки), чтобы не создавать лишних узлов в DOM:

  • Закрывайте все теги: В HTML тег <input> или <img> можно не закрывать. В JSX это вызовет ошибку. Обязательно пишите <input />, <img />, <br />.
  • CamelCase для атрибутов: Поскольку JSX — это JavaScript, некоторые слова зарезервированы. Например, вместо HTML-атрибута class нужно использовать className, а вместо for (в лейблах) — htmlFor. Свойства стилей, состоящие из нескольких слов, также пишутся слитно с большой буквы: tabIndex, onClick.
  • Вставка JavaScript-выражений: Чтобы использовать переменную или выполнить функцию внутри JSX, используйте фигурные скобки {}.
  • Создание первого компонента

    В современном React компоненты — это просто JavaScript-функции. Они принимают данные (пропсы) и возвращают JSX.

    Давайте создадим простой компонент кнопки.

    Обратите внимание: название компонента должно начинаться с заглавной буквы. Если вы назовете функцию myButton, React подумает, что это обычный HTML-тег, и ничего не сработает.

    Теперь мы можем использовать этот компонент внутри другого компонента (например, главного компонента приложения App):

    В этом примере мы дважды использовали компонент MyButton. Это и есть принцип переиспользования.

    Пропсы (Props): Передача данных

    Компоненты были бы бесполезны, если бы они всегда отображали одно и то же. Чтобы сделать их динамическими, мы используем Props (сокращение от properties — свойства).

    Пропсы — это данные, которые родительский компонент передает дочернему. Они похожи на атрибуты в HTML или аргументы функции.

    Как передать пропсы?

    Представьте, что мы хотим сделать компонент Greeting, который приветствует пользователя по имени.

    В родительском компоненте мы передаем данные как атрибуты:

    Как принять пропсы?

    Дочерний компонент получает пропсы как единственный аргумент функции. Обычно этот аргумент называют props.

    В современном JavaScript часто используют деструктуризацию, чтобы сразу извлечь нужные свойства. Это делает код чище:

    Важное правило: Пропсы доступны только для чтения

    Это один из самых важных принципов React. Компонент никогда не должен изменять свои собственные пропсы.

    С точки зрения React, компоненты должны быть «чистыми» функциями относительно своих пропсов. Это значит, что для одних и тех же входных данных они всегда должны возвращать один и тот же результат и ничего не менять во внешнем мире или во входных данных.

    Неправильно (мутация пропсов):

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

    Вложенность и композиция

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

    Пример компонента-обертки (Card):

    Здесь всё, что находится внутри <Card>...</Card>, попадает в пропс children и рендерится внутри div с классом card-style.

    Заключение

    Сегодня мы заложили первый камень в фундамент вашего понимания React. Мы разобрали:

  • Компоненты — строительные блоки приложения.
  • JSX — синтаксис, позволяющий писать разметку внутри JS.
  • Пропсы — механизм передачи данных от родителя к ребенку.
  • Эти три концепции покрывают огромную часть того, что вы будете делать как React-разработчик. В следующей статье мы оживим наши компоненты, добавив им интерактивности с помощью State (состояния) и хуков.

    2. Интерактивность интерфейса: работа с состоянием (useState) и событиями

    Интерактивность интерфейса: работа с состоянием (useState) и событиями

    В предыдущей статье мы научились создавать компоненты и передавать в них данные с помощью пропсов (props). Мы сравнили пропсы с аргументами функции: они приходят извне и влияют на то, что отображает компонент. Однако у пропсов есть одно критическое ограничение — они доступны только для чтения. Компонент не может изменить свои пропсы, так же как функция не должна менять переданные ей аргументы в чистом функциональном программировании.

    Но как тогда создать интерактивное приложение? Как сделать так, чтобы при нажатии на кнопку открывалось меню, в поле ввода появлялся текст, а счетчик лайков увеличивался? Для этого компоненту нужна «память», в которой он может хранить данные, изменяющиеся со временем. В React эта память называется состоянием (State).

    Сегодня мы разберем, как обрабатывать события (клики, ввод текста) и как использовать хук useState для управления состоянием.

    Обработка событий в React

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

    Синтаксис событий

    В React события пишутся в стиле camelCase (верблюжий регистр), а не в нижнем регистре, как в HTML. Кроме того, в качестве обработчика события вы передаете саму функцию, а не строку с кодом.

    HTML:

    React:

    Обратите внимание на отсутствие круглых скобок после activate в примере React. Если вы напишете onClick={activate()}, функция вызовется сразу же при отрисовке компонента, а не при клике. Нам же нужно передать функцию, чтобы React вызвал её позже, когда событие наступит.

    Пример простого обработчика

    Давайте создадим кнопку, которая выводит сообщение в консоль при нажатии:

    Вы также можете определять функцию прямо внутри JSX, используя стрелочные функции:

    Это удобно для коротких операций, но для сложной логики лучше выносить функцию отдельно для чистоты кода.

    Проблема обычных переменных

    Может возникнуть вопрос: зачем нам какая-то специальная концепция «состояния», если мы можем просто использовать переменные JavaScript? Давайте попробуем реализовать счетчик, используя обычную переменную let.

    Если вы запустите этот код, то увидите, что в консоли значение count действительно увеличивается. Однако на экране кнопка по-прежнему будет показывать «Нажато раз: 0». Почему?

  • Локальные переменные не сохраняются между рендерами. Когда React обновляет компонент, он вызывает функцию заново. Переменная count снова инициализируется нулем.
  • Изменение переменных не запускает рендер. React не следит за вашими локальными переменными. Он не знает, что данные изменились и нужно обновить интерфейс.
  • Чтобы решить эти проблемы, нам нужен инструмент, который сохраняет данные между вызовами функции и сообщает React о необходимости перерисовки. Этим инструментом является хук useState.

    Хук useState: добавляем память компоненту

    Хуки (Hooks) — это специальные функции в React, которые позволяют «подцепиться» к возможностям библиотеки внутри функциональных компонентов. Все хуки начинаются с префикса use.

    useState — самый базовый и важный хук. Он позволяет добавить переменную состояния в ваш компонент.

    Как использовать useState

    Для начала его нужно импортировать:

    Синтаксис вызова выглядит так:

    Давайте разберем эту строку детально:

  • initialValue: Это начальное значение состояния (например, 0 для счетчика или '' для текста).
  • state (первый элемент массива): Текущее значение состояния. Вы используете его при рендеринге.
  • setState (второй элемент массива): Функция, которая обновляет состояние. Когда вы её вызываете, React обновляет переменную state и перерисовывает компонент.
  • Эта конструкция const [something, setSomething] называется деструктуризацией массива. useState всегда возвращает массив из двух элементов, и мы просто присваиваем им понятные имена.

    !Циклический процесс обновления интерфейса: действие пользователя вызывает изменение состояния, что приводит к новой отрисовке компонента с актуальными данными.

    Рабочий пример счетчика

    Теперь перепишем наш неработающий счетчик правильно:

    Что происходит при нажатии:

  • Пользователь кликает кнопку, срабатывает handleClick.
  • Вызывается setCount(count + 1). Например, 0 + 1.
  • React «запоминает», что новое значение count теперь 1, и ставит в очередь обновление компонента.
  • React снова вызывает функцию Counter.
  • В этот раз useState(0) вернет уже 1, а не 0.
  • Компонент возвращает JSX с новым текстом «Нажато раз: 1».
  • React обновляет DOM в браузере.
  • Изоляция состояния

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

    Если вы нажмете на первую кнопку, изменится только её счетчик. Вторая кнопка останется без изменений. Это позволяет создавать независимые, переиспользуемые части интерфейса.

    Работа с полями ввода (Forms)

    В веб-разработке мы часто работаем с формами. В React принят подход управляемых компонентов (Controlled Components). Это значит, что значение в поле ввода (input) полностью контролируется состоянием React.

    Давайте создадим поле, которое отображает текст, вводимый пользователем, в реальном времени.

    Здесь мы связываем состояние с интерфейсом двумя путями:

  • value={text}: Мы говорим инпуту, что его значение всегда равно переменной состояния text.
  • onChange={handleChange}: При каждом нажатии клавиши мы берем новое значение из события и обновляем состояние через setText.
  • Это создает «петлю данных»: ввод пользователя -> обновление State -> обновление value в input.

    Обновление состояния на основе предыдущего

    Иногда новое состояние зависит от старого. Например, если мы хотим увеличить счетчик три раза подряд в одной функции.

    Вы удивитесь, но это увеличит счетчик всего на 1, а не на 3. Это происходит потому, что count внутри функции имеет значение на момент начала рендера (например, 0). React видит три команды: setCount(0 + 1), setCount(0 + 1), setCount(0 + 1).

    Чтобы исправить это, нужно передать в функцию обновления callback-функцию:

    Здесь prevCount — это гарантированно самое последнее, актуальное значение состояния. Теперь React выполнит операции последовательно, и счетчик увеличится на 3.

    Правила использования хуков

    Хуки — мощный инструмент, но у них есть два строгих правила, которые нельзя нарушать, иначе магия React сломается:

  • Используйте хуки только на верхнем уровне. Не вызывайте хуки внутри циклов, условий или вложенных функций. useState всегда должен вызываться в одном и том же порядке при каждом рендере.
  • Неправильно:

  • Вызывайте хуки только из React-функций. Не используйте их в обычных JavaScript-функциях (если это не кастомные хуки).
  • Заключение

    Сегодня мы сделали огромный шаг вперед. Теперь ваши интерфейсы могут реагировать на пользователя и запоминать данные. Мы изучили:

    * Как обрабатывать события через onClick, onChange и другие атрибуты. * Почему обычные переменные не подходят для хранения данных интерфейса. * Как использовать useState для создания реактивных переменных. * Как связывать поля ввода с состоянием.

    В следующей статье мы разберем более сложные сценарии: как работать с массивами и объектами в состоянии, и почему мутабельность — главный враг React-разработчика.

    3. Жизненный цикл компонентов и побочные эффекты с хуком useEffect

    Жизненный цикл компонентов и побочные эффекты с хуком useEffect

    В предыдущих статьях мы научились создавать компоненты, передавать им данные через пропсы и делать их интерактивными с помощью хука useState. Теперь наши приложения могут реагировать на действия пользователя. Но что, если нам нужно взаимодействовать с внешним миром?

    Например, загрузить данные с сервера, запустить таймер, изменить заголовок вкладки браузера или подписаться на события прокрутки окна. Эти действия выходят за рамки простого возврата JSX и называются побочными эффектами (side effects).

    В React для работы с побочными эффектами и управления жизненным циклом компонента используется хук useEffect. Сегодня мы разберем, как он работает, почему он так важен и как избежать распространенных ошибок при его использовании.

    Что такое жизненный цикл компонента?

    У каждого React-компонента, как и у живого организма, есть свой жизненный цикл. Он состоит из трех основных фаз:

  • Монтирование (Mounting): Компонент создается и впервые добавляется в DOM (появляется на экране).
  • Обновление (Updating): Компонент получает новые пропсы или у него меняется состояние (state), что приводит к повторному рендеру.
  • Размонтирование (Unmounting): Компонент удаляется из DOM (исчезает с экрана).
  • !Диаграмма фаз жизни компонента: рождение, жизнь с изменениями и удаление.

    Раньше, в классовых компонентах, для каждой фазы были свои методы (componentDidMount, componentDidUpdate и т.д.). В функциональных компонентах мы используем единый инструмент — useEffect.

    Основы синтаксиса useEffect

    Хук useEffect позволяет вам сказать React: «Сделай что-нибудь после того, как отрисуешь компонент».

    useEffect принимает два аргумента:

  • Функция-эффект (callback): Код, который нужно выполнить.
  • Массив зависимостей (dependency array): Необязательный второй аргумент, который указывает, когда именно нужно запускать эффект.
  • Давайте рассмотрим три основных сценария использования useEffect в зависимости от массива зависимостей.

    Сценарий 1: Эффект без зависимостей

    Если вы не передадите второй аргумент (массив), эффект будет запускаться после каждого рендера.

    Это поведение похоже на комбинацию монтирования и обновления. Будьте осторожны: если внутри такого эффекта вы измените состояние (setState), это вызовет новый рендер, который снова запустит эффект, и вы получите бесконечный цикл.

    Сценарий 2: Эффект при монтировании (пустой массив)

    Чаще всего нам нужно выполнить действие только один раз — когда компонент впервые появился на экране. Например, запросить список товаров с сервера.

    Для этого вторым аргументом передается пустой массив [].

    React видит пустой массив и понимает: «Этому эффекту не нужны никакие данные из пропсов или состояния, поэтому мне не нужно запускать его снова».

    Пример: Изменение заголовка документа

    Сценарий 3: Эффект с зависимостями

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

    Мы добавляем переменную в массив зависимостей:

    Частые ошибки

    1. Отсутствие зависимостей

    Если вы используете переменную внутри эффекта, но забыли добавить её в массив зависимостей, эффект будет работать со старыми данными (замыканиями). Современные линтеры (ESLint plugin for React Hooks) обычно предупреждают об этом.

    2. Бесконечные циклы

    Здесь эффект меняет count, изменение count вызывает рендер, рендер запускает эффект снова... и так до зависания браузера.

    Заключение

    Хук useEffect — это мощный инструмент, который синхронизирует ваш компонент с внешними системами. Помните три главных правила:

  • Используйте [] для действий при запуске.
  • Указывайте переменные в [...], чтобы реагировать на их изменения.
  • Возвращайте функцию для очистки таймеров и подписок.
  • В следующей статье мы рассмотрим создание собственных (кастомных) хуков, чтобы выносить логику из компонентов и делать код чище.

    4. Навигация и маршрутизация в приложении с React Router

    Навигация и маршрутизация в приложении с React Router

    Мы прошли долгий путь. Мы научились создавать компоненты, передавать им данные через пропсы, оживлять их с помощью состояния (useState) и даже общаться с внешним миром через побочные эффекты (useEffect). Но до сих пор все наши приложения существовали в рамках одной «страницы».

    В реальном мире веб-приложения редко состоят из одного экрана. У нас есть «Главная», «О нас», «Каталог», «Профиль пользователя» и так далее. Как реализовать переходы между этими разделами, не теряя преимуществ React? Для этого нам понадобится маршрутизация (routing).

    Сегодня мы познакомимся с React Router — стандартом де-факто для навигации в мире React.

    SPA: Иллюзия многостраничности

    Прежде чем писать код, важно понять концепцию Single Page Application (SPA) — одностраничного приложения.

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

    React работает иначе. Это SPA. Технически у вас всегда загружен один HTML-файл (index.html). Когда пользователь кликает «Перейти в профиль», браузер не перезагружает страницу. Вместо этого JavaScript перехватывает клик, меняет URL в адресной строке и подменяет одни компоненты на другие.

    !Сравнение жизненного цикла страницы в классическом веб-сайте и в SPA.

    React Router — это библиотека, которая управляет этим процессом. Она следит за URL в браузере и решает, какой набор компонентов показать пользователю в данный момент.

    Установка и настройка

    React Router не встроен в React, это отдельная библиотека. Установим её:

    Чтобы маршрутизация заработала, нам нужно обернуть все наше приложение в компонент BrowserRouter. Обычно это делается в файле index.js (или main.jsx).

    BrowserRouter использует History API браузера, чтобы синхронизировать интерфейс с URL.

    Создание маршрутов

    Теперь перейдем в App.js и настроим наши маршруты. Нам понадобятся два компонента: Routes и Route.

    * Routes: Это контейнер, который работает как инструкция switch. Он просматривает все вложенные маршруты и выбирает первый, который совпадает с текущим URL. * Route: Это правило. Оно говорит: «Если путь в браузере равен X, покажи компонент Y».

    Предположим, у нас есть три компонента-страницы: Home, About и Contact.

    Теперь, если вы вручную введете в браузере http://localhost:3000/about, React Router увидит совпадение с путем /about и отрисует компонент <About />.

    Навигация: Link вместо тега a

    Как пользователю переходить между страницами? В обычном HTML мы используем тег <a>.

    Если вы используете обычную ссылку, браузер выполнит стандартный переход с перезагрузкой страницы. Все состояние вашего приложения (переменные в useState, данные в Redux) сбросится. Это убивает смысл SPA.

    Вместо этого используйте компонент Link из react-router-dom:

    Визуально Link рендерится как обычный тег <a>, но при клике он предотвращает перезагрузку и использует внутренние механизмы роутера для смены URL.

    Динамические маршруты

    Часто нам нужно создавать страницы по шаблону. Например, страница товара в интернет-магазине или профиль пользователя. Мы не можем создать отдельные маршруты /user/1, /user/2, /user/3 вручную.

    Для этого используются параметры URL. Они обозначаются двоеточием.

    Теперь этот маршрут сработает для /users/1, /users/alex, /users/123 и так далее.

    Хук useParams

    Как внутри компонента UserProfile узнать, какой именно ID был в адресе? Для этого есть хук useParams.

    Обратите внимание, как это связано с предыдущей темой про useEffect. Когда мы переходим от пользователя 1 к пользователю 2, компонент не пересоздается заново, а обновляется. id меняется, срабатывает эффект, и мы загружаем новые данные.

    Обработка несуществующих страниц (404)

    Что если пользователь введет адрес, которого нет в вашем приложении? React Router просто ничего не отрисует, и экран будет пустым. Это плохой UX.

    Чтобы показать страницу ошибки 404, добавьте маршрут со звездочкой * в самый конец списка.

    Программная навигация

    Иногда нужно перенаправить пользователя не по клику на ссылку, а в результате выполнения кода. Например, после успешной отправки формы логина перебросить его в личный кабинет.

    Для этого используется хук useNavigate.

    Вложенные маршруты и Layouts

    В большинстве приложений есть общие элементы интерфейса: шапка (Header), подвал (Footer), боковая панель (Sidebar). Копировать их в каждый компонент страницы — плохая практика.

    React Router позволяет использовать вложенные маршруты (Nested Routes) и компонент Outlet для создания макетов (Layouts).

    Создадим компонент-обертку MainLayout:

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

    !Визуализация работы компонента Outlet внутри Layout-компонента.

    Когда URL равен /about, React отрисует MainLayout, а внутри него, вместо Outlet, подставит About.

    NavLink: Ссылки с активным состоянием

    Для меню навигации часто нужно подсвечивать текущую активную ссылку. Вместо обычного Link можно использовать NavLink.

    По умолчанию он добавляет класс active к ссылке, если её путь совпадает с текущим URL. Вы также можете настроить стили через функцию:

    Заключение

    Маршрутизация превращает набор разрозненных компонентов в полноценное приложение. Сегодня мы узнали:

  • BrowserRouter — подключает приложение к URL браузера.
  • Routes и Route — определяют, какой компонент показать для конкретного пути.
  • Link — позволяет переходить между страницами без перезагрузки.
  • useParams — помогает читать динамические параметры (например, ID товара).
  • useNavigate — позволяет менять страницу программно.
  • Outlet — мощный инструмент для создания общих макетов страниц.
  • Теперь у вас есть все инструменты для создания сложного многостраничного приложения. В следующей статье мы поговорим о том, как оптимизировать наше приложение и работать с формами на профессиональном уровне.

    5. Работа с API, управление глобальным состоянием и сборка проекта

    Работа с API, управление глобальным состоянием и сборка проекта

    Поздравляю! Вы прошли огромный путь. От простых компонентов и JSX мы добрались до маршрутизации и создания многостраничных приложений. Теперь у вас есть структура, но вашему приложению, скорее всего, не хватает двух вещей: реальных данных и способа удобно управлять ими.

    В этой заключительной статье курса мы свяжем всё воедино. Мы научимся получать данные с сервера, избавимся от бесконечной передачи пропсов с помощью Context API и подготовим наше приложение к публикации в интернете.

    Взаимодействие с внешним миром: Работа с API

    До сих пор мы хранили данные прямо в коде (hardcoded data). В реальных приложениях данные (списки товаров, профили пользователей, сообщения) хранятся на удаленном сервере — бэкенде. Чтобы получить их, фронтенд должен отправить запрос.

    Интерфейс, через который общаются фронтенд и бэкенд, называется API (Application Programming Interface).

    Представьте, что вы в ресторане. Вы (фронтенд) не идете на кухню (базу данных), чтобы приготовить еду. Вы зовете официанта (API) и делаете заказ. Официант уносит заказ на кухню, а затем приносит вам результат — готовое блюдо или сообщение о том, что ингредиенты закончились (ошибка).

    Использование fetch внутри useEffect

    В JavaScript есть встроенный метод fetch для отправки сетевых запросов. Поскольку запрос к серверу — это побочный эффект, в React мы выполняем его внутри хука useEffect.

    Рассмотрим классический паттерн загрузки данных. Нам понадобятся три состояния:

  • data: для хранения полученных данных.
  • isLoading: чтобы показать спиннер, пока данные летят.
  • error: чтобы сообщить пользователю, если что-то пошло не так.
  • Этот шаблон вы будете использовать в 90% случаев при работе с API в простых приложениях.

    Проблема Prop Drilling (Сверление пропсов)

    По мере роста приложения вы столкнетесь с неприятной ситуацией. Представьте, что у вас есть данные о текущем пользователе (имя, аватар) в самом главном компоненте App. А отобразить аватар нужно в компоненте Header, который находится внутри Layout, который внутри App.

    Вам придется передавать проп user через все промежуточные компоненты, даже если они сами эти данные не используют.

    Это называется Prop Drilling. Это делает код запутанным и сложным для поддержки.

    !Сравнение передачи данных через пропсы (Prop Drilling) и через Context API.

    Глобальное состояние с Context API

    React предлагает встроенное решение — Context API. Контекст позволяет передавать данные через дерево компонентов без необходимости передавать пропсы на промежуточных уровнях вручную.

    Работа с контекстом состоит из трех шагов:

    1. Создание контекста

    Создадим отдельный файл UserContext.js:

    2. Предоставление данных (Provider)

    Обернем часть приложения, которой нужны данные, в компонент Provider. Обычно это делается в App.js.

    3. Потребление данных (useContext)

    Теперь в любом вложенном компоненте (например, Profile) мы можем получить данные напрямую, используя хук useContext.

    Обратите внимание: компонент Header и main мы не трогали, данные «перелетели» через них. Контекст идеально подходит для глобальных данных: темы оформления (светлая/темная), языка интерфейса, данных пользователя.

    Для более сложного управления состоянием (например, в огромных интернет-магазинах) используют библиотеки вроде Redux или Zustand, но Context API — это база, с которой стоит начать.

    Сборка и деплой (Build & Deploy)

    Вы написали код, он работает на localhost:3000. Но как показать его миру? Вы не можете просто скинуть папку с проектом другу, у которого не установлен Node.js.

    Браузеры не понимают JSX и многие современные функции JavaScript напрямую. Кроме того, ваш код разбросан по десяткам файлов. Процесс превращения вашего кода в набор оптимизированных файлов, понятных браузеру, называется сборкой (build).

    Что происходит во время сборки?

  • Транспиляция: Превращение JSX и современного JS в старый добрый JavaScript (ES5/ES6), который работает во всех браузерах.
  • Минификация: Удаление всех пробелов, комментариев и сокращение имен переменных для уменьшения размера файлов.
  • Бандлинг (Bundling): Объединение сотен маленьких файлов в один или несколько больших файлов (bundle.js).
  • Как собрать проект?

    Если вы используете Create React App или Vite (что является современным стандартом), у вас уже есть скрипт для сборки.

    Откройте терминал и введите:

    После завершения процесса в папке проекта появится новая директория build (или dist в Vite). Внутри вы увидите: * index.html — единственный HTML файл. * Папки js и css с непонятными названиями файлов (например, main.8a2b3c.js).

    Именно содержимое папки build/dist — это ваше готовое приложение. Это просто статические файлы. Их можно открыть даже без React, просто на любом веб-сервере.

    Публикация (Deploy)

    Самый простой способ опубликовать React-приложение бесплатно — использовать сервисы вроде Netlify, Vercel или GitHub Pages.

    Для Netlify, например, процесс выглядит так:

  • Регистрируетесь на сайте.
  • Перетаскиваете папку build (или dist) в специальное окно в браузере.
  • Через несколько секунд получаете ссылку на ваш работающий сайт.
  • Заключение курса

    Поздравляю! Вы завершили курс «Основы веб-разработки на ReactJS». Давайте вспомним, чему мы научились:

  • Компоненты и JSX: Мы научились мыслить блоками и писать разметку внутри JS.
  • Props и State: Разобрались, как передавать данные и как заставить интерфейс реагировать на изменения.
  • Хуки: Освоили useState для памяти и useEffect для побочных эффектов.
  • Роутинг: Превратили одну страницу в полноценное приложение с навигацией.
  • API и Контекст: Научились работать с сервером и управлять глобальными данными.
  • React — это огромная экосистема. Дальше вас ждут изучение TypeScript, библиотек для форм (React Hook Form), стейт-менеджеров (Redux Toolkit) и фреймворков (Next.js). Но фундамент у вас уже есть, и он очень прочный.

    Удачи в создании ваших первых приложений!