Зачем фронтендерам React, если есть JavaScript
- 8 апреля 2022
Сайты на чистом JavaScript давно стали редкостью: обычно при разработке используют библиотеки и фреймворки. Одна из самых популярных библиотек — React. В этой статье мы познакомимся с её основными принципами и идеями. Мы расскажем, что из себя представляет React, какие у него преимущества в сравнении с другими инструментами и как работать с React-компонентами.
Зачем нужны реактивные фреймворки и библиотеки?
Современные сайты отличаются от тех, которыми мы пользовались раньше: они более динамичны. С их помощью можно покупать товары, общаться с друзьями или писать комментарии.
Изменилась и структура сайтов. Изначально они состояли из набора отдельных HTML-страниц. Сейчас они представляют собой один HTML-документ, внешний вид которого меняется динамически через JavaScript.
Такой подход получил название SPA — single-page application, или одностраничное приложение. SPA делает сайты полноценными приложениями, которые не перезагружаются между переходами по страницам. Чтобы выполнить переход, нужно полностью перерисовать контент документа с помощью JavaScript и полученных данных.
Хотя требования к интерактивности сайтов выросли, инструменты для её создания почти не изменились. Работа с DOM по-прежнему остаётся императивной, «из коробки», и выглядит примерно так:
<h1>Привет, Мир!!! Меня зовут <b class="js-name"></b>.</h1>
function setName(name) {
const nameWrapper = document.querySelector(".js-name");
if (nameWrapper) {
nameWrapper.textContent = name;
}
}
setName("Вася");
Этот код может показаться неплохим, если нужно добавить имя пользователя в строку приветствия или создать слайдер. Но предположим, мы делаем SPA-приложение с такой корзиной:
И эту корзину нужно перерисовать в страницу оформления заказа:
В этом случае решение задачи «в лоб» будет невероятно трудоёмким. Придётся написать тысячи строк кода взаимодействия с DOM API — такой код будет сложно читать и поддерживать. Использование библиотеки наподобие jQuery лишь поменяет интерфейс взаимодействия с DOM, но не решит проблему.
Можно написать свою реализацию MV* паттерна и настроить связывание данных, построив свою систему рендеринга. Но такие решения сложно реализовать быстро и качественно, а новым членам команды разработки будет непросто разобраться в чужих паттернах.
Подобные сложности привели к созданию реактивных фреймворков и библиотек. Идея реактивности такова: вместо того, чтобы каждый раз вручную в коде в императивном виде менять интерфейс приложения, гораздо удобнее изначально в декларативном виде задать связь между данными и их отображением и в дальнейшем в коде менять только данные. Интерфейс будет перерисовываться автоматически под новые данные.
То есть реактивный подход подразумевает работу с данными, при изменении которых автоматически меняются и другие части программы, в том числе интерфейс. React стал одной из первых и самой популярной на начало 2022 года реактивной библиотекой для работы с интерфейсами.
💫 Начните кодить на React
Научитесь собирать интерфейсы в экосистеме React с нуля и создавать интерактивные React-компоненты.
Что такое React?
React — это декларативная JavaScript-библиотека для создания пользовательских интерфейсов. Она позволяет собирать сложный UI из маленьких изолированных кусочков кода, называемых «компонентами».
React предоставляет два синтаксиса для создания компонентов: классовый и функциональный. Классовый используется редко, так как синтаксис классов часто излишен для описания компонентов. Поэтому в статье мы будем рассматривать функциональные компоненты.
Функциональный компонент в React — это JavaScript-функция, которая на входе получает объект с данными для отрисовки компонента — их называют props, а на выходе возвращает описание интерфейса, который нужно отобразить.
Пример с приветствием пользователя на React может выглядеть так:
import React from "react";
function HelloWorld (props) {
return (<h1>Привет, Мир!!! Меня зовут <b>{props.name}</b></h1>);
}
export default HelloWorld;
В этом коде легко разобраться, даже если вы не знаете синтаксиса React. Здесь в виде функции описан React-компонент HelloWorld.
На входе он получает объект с данными, props, который содержит свойство name
c именем пользователя. Функция возвращает специальный код, похожий на HTML-разметку. Подробнее о нём расскажем позже, а сейчас лишь важно понимать, что этот код работает. React действительно отобразит на странице DOM-дерево — оно будет соответствовать разметке, которую вернуло HelloWorld.
Но в отличие от обычного HTML, мы смогли подставить в разметку данные из объекта props <b>{props.name}</b>
, тем самым шаблонизировав её.
Код на React выглядит легче и лаконичнее решения на чистом JS. Мы не описываем, как перерисовывать интерфейс. Вместо этого мы указываем, что нужно отобразить на месте компонента, и используем для этого синтаксис, похожий на HTML. Такой подход позволяет относительно легко решать и более сложные задачи. Например, перерисовать разметку страницы корзины и отобразить на её месте интерфейс страницы заказа.
Для своих перерисовок React использует Virtual DOM. Это позволяет обновлять только изменившиеся узлы DOM-дерева, а не перерисовывать всю страницу. Благодаря этому приложения не расходуют лишние ресурсы.
React решает проблемы фронтендеров при разработке интерфейсов динамичных сайтов и SPA-приложений. При использовании классической связки JavaScript и HTML перерисовка интерфейса сильно усложняется. React же не ограничивает возможности разработчика, в отличие от любых фреймворков.
Востребован ли React на рынке фронтенд-разработки? Сравнение с Angular и Vue
Проекты на чистом JavaScript стали экзотикой — чаще разработчики используют реактивные библиотеки и фреймворки: React, Vue или Angular. Трудно понять, какой фреймворк лучше и удобнее — разработчики постоянно спорят и не могут прийти к компромиссу.
На наш взгляд, современные библиотеки и фреймворки похожи друг на друга — каждый из них имеет свои преимущества и недостатки, но в целом они одинаково эффективны. Статьи про сравнение инструментов часто бывают необъективными, так как разработчики полагаются на личные предпочтения. Например, если команда целый год переписывала сайт с Vue на React, то её члены скажут, что React лучше, и наоборот. Поэтому не стоит тратить время на сравнение разных реактивных фреймворков и библиотек. Вместо этого лучше изучить как минимум один из них.
И всё же одно преимущество у React есть — React-разработчиков чаще нанимают. Вот сравнение количества вакансий по React, Angular и Vue на hh.ru:
Количество вакансий для фронтендеров с опытом работы 1-3 года
Компании ищут React-разработчиков в два раза чаще, чем разработчиков на Vue или Angular.
Если сравнивать количество загрузок npm-пакетов, то и здесь React превосходит фреймворки. По данным npm trends за последний год, среднее ежемесячное число загрузок пакета React — 11 млн, Angular и Vue — около 2,8 млн.
Хотя формально их вообще нельзя сравнивать, так как React — библиотека, а Vue и Angular — фреймворки. Однако из-за различных переходных вариаций, таких как «прогрессивный фреймворк», и других особенностей различий между библиотеками и фреймворками во фронтенде почти нет.
Типовые задачи React-разработчика
Типовые задачи разработчика состоят в написании React-компонентов. Далее из таких компонентов строятся страницы сайта.
Реактивные фреймворки — это программирование на основе работы с данными, поэтому важно знать тип данных, который приходит в компоненты. Так как JavaScript не позволяет явно описывать типы данных, React-разработчики обычно используют в проектах TypeScript.
React отвечает только за отображение интерфейса. Поэтому вокруг него есть целая экосистема инструментов, решающих остальные задачи фронтенд-разработки:
Управление состоянием — библиотеки для работы с глобальными данными приложения, которые не относятся к конкретному компоненту, а нужны во многих частях сайта. Среди популярных инструментов для управления состоянием можно выделить Redux и Mobx.
Роутинг. SPA подразумевает переход между страницами сайта без дополнительных запросов к серверу. Поэтому задачами роутинга, соответствия страниц определённым URL, тоже занимаются фронтендеры. Для таких задач существует ряд популярных библиотек, в частности, React Router.
Серверный рендеринг. Одна из проблем SPA — многие поисковики ожидают HTML, а не JavaScript. Поэтому важно отдавать на запросы поисковиков не пустой HTML-файл, на котором JavaScript «рисует» интерфейс, а готовую HTML-разметку. Чтобы её генерировать из компонентов, разработан фреймворк Next.js.
Создание UI-элементов. Типовые UI-элементы обычно не пишут с нуля — для них используют готовые UI-библиотеки: MUI, Ant Design и многие другие.
Стилизация. Для стилизации в React часто используют не обычный CSS, а подход CSS-in-JS. Он позволяет описывать стили прямо в JavaScript. Одна из самых популярных реализаций подхода CSS-in-JS — библиотека styled-components.
Это далеко не полный список задач и инструментов, с которыми работает React-разработчик в повседневной жизни.
Как работать с React-компонентами?
Рассмотрим подробнее синтаксис компонентов. Как мы уже говорили, React-компонент — это JavaScript-функция, которая на входе получает объект с данными для отрисовки компонента, а на выходе возвращает React-элемент.
React-элемент — это JavaScript-объект, описывающий узел DOM-дерева. Он имеет специальный формат, который React умеет обрабатывать и отображать на странице. Для создания таких объектов библиотека React предоставляет метод React.createElement
.
Чтобы создать на странице разметку <p>Тяжело читать <b>React.createElement</b>!!!</p>,
можно написать React-компонент:
import React from "react";
function HelloReact() {
// не нужно думать, что это такое, дальше мы будем использовать JSX
return React.createElement(
"p",
{},
"Тяжело читать ",
React.createElement("b", {}, "React.createElement"),
"!!!"
);
}
Вызовы React.createElement
не выглядят интуитивно понятными. Глядя на код, сложно понять, что будет выведено на страницу. Поэтому React.createElement
обычно напрямую не применяется, а используется специальный синтаксис JSX.
Что такое JSX?
JSX — расширение JavaScript для описания интерфейса прямо в JS с помощью синтаксиса, похожего на HTML. С использованием JSX пример будет выглядеть так:
import React from "react";
function HelloReact() {
return <p>Тяжело читать <b>React.createElement</b>!!!</p>
}
С JSX код стал понятнее. Сразу видно, какой фрагмент DOM-дерева описывает компонент.
JSX позволяет шаблонизировать разметку, подставляя в неё данные, вычисленные из JavaScript-выражений. Для этого используется синтаксис фигурных скобок. Если переписать пример из начала статьи на React, то он может выглядеть так:
import React from "react";
function HelloWorld (props) {
return (<h1>Привет, Мир!!! Меня зовут <b>{props.name}</b></h1>);
}
export default HelloWorld;
Здесь компонент HelloWorld
получает в объекте props
имя пользователя name
и на основе этих данных возвращает нужную разметку: <h1>Привет, Мир!!! Меня зовут <b>{name}</b></h1>
. Благодаря синтаксису фигурных скобок значение из переменной name
подставляется в JSX.
Однако браузер ничего не знает про JSX и не умеет его интерпретировать. При использовании JSX нужно настроить сборку проекта так, чтобы JSX автоматически трансформировался в JavaScript-объекты и в браузер попадал чистый JS. Для этого есть Babel-плагины и пресеты, а также проекты наподобие CreateReactApp. В статье мы используем онлайн IDE CodeSandbox, которая предоставляет готовый шаблон для React-проектов.
Теперь посмотрим, как заставить React вывести на экран JSX-разметку. Для этого React предоставляет метод ReactDOM.render
. Первым параметром в него передаётся JSX-разметка. Вторым — узел DOM-дерева, в который нужно вставить кусочек интерфейса.
Чтобы вывести компонент HelloWorld
в DOM-узел с id root
, нужно написать:
import ReactDOM from "react-dom";
import HelloWorld from "./hello-world";
const rootElement = document.getElementById("root");
ReactDOM.render(HelloWorld({name:"Вася"}) , rootElement);
Вызов HelloWorld
c объектом {name:"Вася"}
вернёт нужную JSX-разметку, а rootElement
хранит ссылку на DOM-элемент с id root
. В результате вызов ReactDOM.render(HelloWorld({name:"Вася"}) , rootElement)
вставит полученный из компонента интерфейс в нужный DOM-узел.
Вручную, как функции, компоненты обычно не вызывают. Дело в том, что в JSX можно вставлять компоненты как обычные HTML-теги, передавая данные через атрибуты. При отрисовке на месте компонента в JSX будет выведена та разметка, которую вернёт компонент.
Имя компонента в JSX должно начинаться с большой буквы, иначе JSX будет идентифицировать его как обычный HTML-тег.
Таким образом, вместо ReactDOM.render(HelloWorld({name:"Вася"}) , rootElement);
пишут: ReactDOM.render(<HelloWorld name="Вася" /> , rootElement);
.
Композиция компонентов и хуки
Возможность вставлять в JSX не только HTML-теги, но и свои компоненты — один из важнейших приёмов в React. Страницы сайта обычно бывают намного сложнее, чем пример Hello World
: они состоят из сотен или даже тысяч HTML-элементов. Описывать такую страницу в одном модуле или компоненте — плохая идея. Код превратится в огромную простыню. Поэтому страницы разбивают на более мелкие кусочки интерфейса, и каждый из них реализуют в виде отдельного компонента. Этот приём в React называют композицией компонентов.
Тот же самый пример с HelloWorld
можно представить в виде композиции двух маленьких компонентов:
// компонент Name
import React from "react";
function Name(props) {
return <b>{props.name}</b>;
}
export default Name;
// компонент HelloWorld
import React from "react";
import Name from "./name";
function HelloWorld(props) {
return (
<h1>
Привет, Мир!!! Меня зовут <Name name={props.name} />
</h1>
);
}
export default HelloWorld;
Теперь за отрисовку имени пользователя отвечает компонент Name.
Его можно использовать не только в HelloWorld
, но и любой другой части интерфейса, где необходимо вывести имя пользователя.
Для более сложных страниц композиция может быть больше, например:
Таким образом, интерфейс в React представляет собой дерево компонентов, каждый из которых отвечает за свой кусочек интерфейса. Так как данные передаются только через props сверху вниз, от родительских компонентов к дочерним, это образует однонаправленный поток данных. Работа с ними становится более предсказуемой и понятной.
Создаваемые с помощью React пользовательские интерфейсы не статичны. Мы можем их перерисовать в ответ на действия пользователя. Для этого React предоставляет React-хуки.
Хуки — это функции, которые позволяют изменить стандартное поведение системы собственным кодом. При этом интерфейс функции ограничивает эти изменения безопасными для системы пределами.
В случае с React хуки помогают управлять жизненным циклом компонента, позволяя в нужный момент вызвать, например, его перерисовку.
В результате счётчик на React может выглядеть так:
import React, { useState } from "react";
export default function Counter({ initValue }) {
const [value, setValue] = useState(initValue || 1);
return (
<div>
<button type="button" onClick={() => setValue(value - 1)}>-</button>
<span> {value} </span>
<button type="button" onClick={() => setValue(value + 1)}>+</button>
</div>
);
}
useState
— специальный React-хук для хранения состояния компонента. Когда состояние меняется, компонент перерисовывается.
При вызове useState
возвращает массив, первый элемент которого — значение состояния. Во втором элементе хранится функция-сеттер, с помощью которой можно менять значение состояния. Для кнопок передан props onClick
. В него записана функция, которая вызывается при нажатии на кнопку — setValue
с новым значением состояния. Это вызывает перерисовку, и на экране отображается актуальное значение value
.
useState
— только один из множества доступных хуков. Более того, при необходимости разработчик может писать свои кастомные хуки.
Итак, какие у React преимущества в сравнении с нативным JavaScript:
- React предоставляет декларативное описание интерфейса — с ним удобнее работать, чем с вереницей императивных инструкций DOM API.
- React сам решает, какие узлы DOM-дерева в какой момент обновлять. Он не выполняет лишних операций, поэтому код на React быстрее, чем большинство наивных реализаций на чистом JavaScript.
- У React отличная документация. Самописные решения для реализации дата биндинга обычно плохо задокументированы или не задокументированы вовсе.
- Благодаря JSX в одном компоненте мы видим и логику, и разметку, с которой должна работать данная логика. Обычно они неразрывно связаны, и видеть их рядом намного удобнее, чем отдельно хранить HTML и JavaScript.
- Разбиение кода на компоненты позволяет переиспользовать код.
Итоги
React востребован в мире современной фронтенд-разработки: многие разработчики по умолчанию используют его для написания интерфейсов. Такая популярность привела к тому, что некоторые джуны начинают изучать React, не зная базовый JavaScript. Это грубая ошибка. React — всего лишь JS-библиотека, и чтобы её освоить, нужно хорошо знать JavaScript.
При изучении React уделите больше времени функциональному синтаксису написания компонентов — он используется чаще. На классовых компонентах, как правило, осталось написанным только «легаси». Также советуем освоить TypeScript, ведь его применяют в большинстве проектов на React.
У React есть своя философия, приёмы и ограничения, которые нужно соблюдать, чтобы писать качественный код. Поэтому важно не просто выучить синтаксис, но и общаться с более опытными коллегами, показывать им свой код. Только так вы сможете стать хорошим React-разработчиком.
Чтобы было проще выбрать:
«Доктайп» — журнал о фронтенде. Читайте, слушайте и учитесь с нами.
Читать дальше
300кк в наносекунду
Игра, где нужно забрать своё и продержаться ещё один день.
- 7 марта 2024
9 книг по JavaScript для начинающих в 2024
Все вокруг говорят, что книги — прошлый век. Но вовремя прочитанная хорошая книжка может здорово помочь в изучении нового языка или технологии, а то и вообще целиком объяснить какую-нибудь важную штуку. Например, какие бывают алгоритмы, или зачем нужен рефакторинг. К тому же, хоть фреймворки меняются каждый год, основы обычно долго не меняются.
Мы опросили знакомых разработчиков, узнали, что читают они сами, и предлагаем вам подборку хороших книг по JavaScript.
- 6 марта 2024
Объект URL в JavaScript: полный разбор
Объект URL
в JavaScript представляет URL-адрес и предоставляет удобные методы для работы с ним. Он позволяет анализировать, конструировать и декодировать URL-адреса.
Создать объект URL
можно двумя способами:
Конструктор URL()
— самый распространённый способ, в котором вы передаёте любой URL в виде строки в качестве аргумента.
const url = new URL("https://www.example.com/path?query=123#hash");
Использование window.location
— это глобальный объект в браузерах, который содержит информацию о текущем URL.
const currentUrl = new URL(window.location.href);
- 23 января 2024
Генерация QR-кодов на JS в 4 шага. Node.js + qrcode
Давайте сделаем простой REST API на Node.js и Express, который будет генерировать QR-коды для любой ссылки. Если у вас ещё не установлены Node.js
и npm
, установите их с официального сайта.
- 22 ноября 2023
ChatGPT не справляется
Притворитесь нейросетью и решите 101 задачку по JavaScript как можно быстрее.
- 2 ноября 2023
Знакомство с JavaScript
Теперь, когда вы знаете, как создать структуру веб-страницы с помощью HTML и оформить ее стилями с помощью CSS, пришло время оживить её с помощью JavaScript (JS). JavaScript — это мощный язык программирования, который используется для создания интерактивных и динамических веб-сайтов.
Вы можете добавить JavaScript в ваш HTML-документ двумя способами:
Встроенный JavaScript: непосредственно в HTML-документ, в тегах <script>
:
<script>
alert("Привет, мир!");
</script>
Внешний JavaScript: подключение внешнего .js
файла к HTML-документу:
<script src="script.js"></script>
- 1 ноября 2023
Событие onclick в JS на примерах
Интерактивность — ключевой компонент любого современного сайта. И одним из наиболее часто используемых событий для создания интерактивности является событие onclick
. В этой статье мы подробно разберёмся, что такое событие onclick
, как его использовать и приведем примеры применения.
Событие onclick
— это событие JavaScript, которое активируется, когда пользователь кликает на определенный элемент страницы. Это может быть кнопка, ссылка, изображение или любой другой элемент, на который можно нажать.
- 30 октября 2023
Как перевернуть сайт. Самая короткая инструкция
Не представляем, зачем это может понадобиться, но не могли пройти мимо.
Никакой магии. Мы вызываем JavaScript-функцию rotateBody()
, которая применяет свойство transform
с значением rotate(180deg)
к элементу <body>
. Когда вы нажмете на кнопку «Перевернуть», всё, что находится внутри <body>
будет повернуто на 180 градусов (то есть, встанет вниз головой)
function rotateBody() {
document.body.style.transform = 'rotate(180deg)';
}
<button onclick="rotateBody()">Перевернуть</button>
Но такой код повернёт страницу только один раз. Если нужно, чтобы она возвращалась обратно при втором клике, усложним код:
let isRotated = false;
function rotateBody() {
if (isRotated) {
document.body.style.transform = 'rotate(0deg)';
document.body.style.direction = "ltr";
} else {
document.body.style.transform = 'rotate(180deg)';
document.body.style.direction = "rtl";
}
isRotated = !isRotated;
}
Надеемся, вы прочитали это описание до того, как нажать на кнопку.
- 25 октября 2023
Как узнать геолокацию: Geolocation API
Geolocation API позволяет сайтам запрашивать, а пользователям предоставлять свое местоположение веб-приложениям. Геолокация может использоваться для выбора города в интернет-магазине, отображения пользователя на карте или навигации в ближайший гипермаркет.
Основной метод Geolocation API — getCurrentPosition()
, но есть и другие методы и свойства, которые могут пригодиться.
- 16 октября 2023
Что такое localStorage и как им пользоваться
localStorage
— это место в браузере пользователя, в котором сайты могут сохранять разные данные. Это как ящик для хранения вещей, которые не исчезнут, даже если вы выключите компьютер или закроете браузер.
До localStorage
разработчики часто использовали cookies, но они были не очень удобны: мало места и постоянная передача данных туда-сюда. LocalStorage появился, чтобы сделать процесс более простым и эффективным.
- 12 октября 2023