Олег Марков
Что такое frontend-разработка на React
Введение
Frontend-разработка на React — это один из самых популярных и востребованных способов создания современных пользовательских интерфейсов для веб-приложений. React, разработанный компанией Facebook в 2013 году, быстро завоевал доверие разработчиков благодаря своей гибкости, высокой производительности и богатой экосистеме. Если вы открываете сайт, который мгновенно реагирует на ваши действия, обновляет информацию без перезагрузки страницы и выглядит опрятно на любом устройстве, велика вероятность, что под капотом этого сайта работает именно React.
В этой статье вы узнаете, что из себя представляет frontend-разработка на React, как устроен жизненный цикл компонентов, работу со стейтом и пропсами, что такое JSX, виртуальный DOM, Hooks и многое другое. Я покажу вам реальные примеры кода, чтобы вы увидели, как принципы React отражаются в разработке на практике.
Что такое React и почему он популярен
React — это JavaScript-библиотека для построения пользовательских интерфейсов. Она не навязывает жестких архитектурных рамок, позволяя использовать как небольшие компоненты внутри существующего проекта, так и строить сложные одностраничные приложения (SPA) с нуля. Вот несколько ключевых причин, почему React часто выбирают как инструмент для frontend-разработки:
- Компонентный подход: Интерфейс разбивается на независимые части (компоненты), что облегчает повторное использование кода и ускоряет разработку.
- Virtual DOM: React работает с виртуальным представлением DOM, сравнивает его с реальным и обновляет только изменившиеся части. Благодаря этому сайты работают быстрее.
- Однонаправленный поток данных: Передача данных (props) идет сверху вниз, что упрощает понимание и отладку приложений.
- JSX: Позволяет писать разметку (HTML-подобный синтаксис) прямо в JavaScript, делая код более читаемым.
- Разнообразие инструментов: Большое количество библиотек, утилит и крутой комьюнити позволяют реализовать любые задачи — от маршрутизации до управления состоянием приложения.
React используется такими компаниями, как Facebook, Instagram, Netflix, Airbnb, Uber, WhatsApp и многими другими.
Frontend-разработка на React — это создание пользовательских интерфейсов веб-приложений с использованием библиотеки React. Это включает в себя разработку компонентов, управление состоянием, маршрутизацию, взаимодействие с API и другие аспекты, необходимые для создания интерактивных и привлекательных веб-приложений. Если вы хотите узнать больше о frontend-разработке на React и научиться создавать современные веб-приложения — приходите на наш большой курс Основы React, React Router и Redux Toolkit. На курсе 177 уроков и 17 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.
Установка и старт работы с проектом на React
Начать довольно просто. Официально команда React советует использовать Create React App для быстрой и простой инициализации нового проекта. Этот инструмент создаёт всю необходимую структуру и конфигурацию за вас.
Вот пример, как вы можете создать новое приложение на React:
npx create-react-app my-react-app
cd my-react-app
npm start
npx create-react-app my-react-app
— создаёт новый проект с базовой структурой.cd my-react-app
— переходит в папку вашего нового приложения.npm start
— запускает приложение в режиме разработки. Обычно оно будет доступно по адресу http://localhost:3000.
После этого вы увидите стартовую страницу, а все основные файлы для работы находятся в папке src
. Основной файл приложения — src/App.js
.
Компонентный подход в React
React строится вокруг идеи компонентности. Вы описываете интерфейс в терминах маленьких, независимых и переиспользуемых частей. Это делит весь UI на логические блоки, которыми вы управляете отдельно.
Функциональные и классовые компоненты
Сейчас основной способ создания компонентов — функциональные компоненты. Вот базовый пример:
// src/components/Greeting.js
function Greeting(props) {
// props.name принимает значение из родительского компонента
return <h1>Привет, {props.name}!</h1>;
}
Использовать его можно так:
<Greeting name="Сергей" />
Раньше часто писали классовые компоненты, сейчас их используют реже, в основном для обратной совместимости или если компоненту нужен "жизненный цикл" и управление состоянием (до появления хуков):
import React from 'react';
class Greeting extends React.Component {
render() {
return <h1>Привет, {this.props.name}!</h1>;
}
}
Классовые и функциональные компоненты — в чём разница
- Функциональные — проще, легче пишутся и лучше оптимизируются. С выходом хуков могут делать почти всё то же, что и классовые.
- Классовые позволяют использовать методы жизненного цикла через специальные методы (
componentDidMount
,componentDidUpdate
и др.), но функции-хуки предоставляют аналогичные возможности удобнее.
В 2020 году официальная документация рекомендует использовать преимущественно функциональные компоненты.
JSX — расширение синтаксиса для удобства
JSX (JavaScript XML) — расширение синтаксиса JavaScript, позволяющее писать разметку прямо в коде. Благодаря этому можно описывать внешний вид компонентов максимально понятно.
Пример:
function App() {
return (
<div>
<h1>Добро пожаловать на сайт!</h1>
{/* Компонент Greeting, которому передается prop name */}
<Greeting name="Ольга" />
</div>
);
}
JSX внутри преобразуется в обычные вызовы функций, поэтому можно вставлять любые JavaScript выражения внутри фигурных скобок { }
.
Обратите внимание:
- В JSX все элементы должны иметь закрывающий тег.
- Атрибуты, пересекающиеся с ключевыми словами JavaScript, переименованы (например, вместо
class
используетсяclassName
).
Работа с состоянием (state) и свойствами (props)
Props
Props
(от читается как "properties" — свойства) — это способ передавать данные из родительского компонента в дочерний. Они передаются как обычные параметры функции.
function UserCard(props) {
return <p>Имя пользователя: {props.name}</p>;
}
// Использование
<UserCard name="Павел" />
Props изменять внутри дочернего компонента нельзя — они только для чтения.
State
State
(состояние) — это особое свойство компонента, которое хранит данные, способные меняться в ходе жизни компонента (например, счетчик, текущие значения формы).
Вы можете использовать хук useState
для хранения и изменения состояния в функциональных компонентах:
import React, { useState } from 'react';
function Counter() {
// Создаем состояние count с начальным значением 0
const [count, setCount] = useState(0);
// setCount — функция для изменения состояния count
return (
<div>
<p>Текущее значение: {count}</p>
{/* Увеличиваем значение при клике */}
<button onClick={() => setCount(count + 1)}>Плюс 1</button>
</div>
);
}
Здесь вы видите, как изменение состояния мгновенно обновляет интерфейс.
Жизненный цикл компонента
В функциональных компонентах жизненный цикл управляется при помощи хуков (например, useEffect
). Это позволяет выполнять определенные действия при монтировании, обновлении или размонтировании компонента.
Пример использования:
import React, { useState, useEffect } from 'react';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
// Запускаем таймер при монтировании компонента
const interval = setInterval(() => {
setSeconds(s => s + 1); // Увеличиваем seconds каждую секунду
}, 1000);
// Возвращаем функцию очистки (вызывается при размонтировании)
return () => clearInterval(interval);
}, []); // Пустой массив — этот эффект запускается 1 раз
return <p>Секунд прошло: {seconds}</p>;
}
Комментарии в коде объясняют, как работает этот пример.
Virtual DOM и его преимущества
Один из главных плюсов React — виртуальный DOM. Обычно браузер работает с "живым" DOM, который тяжелый и плохо подходит для частых изменений. React создает легкую копию DOM в памяти (virtual DOM), и при любом изменении сравнивает актуальное состояние с предыдущим. Только разницу ("diff") он отправляет в реальную DOM-структуру браузера.
Это значит:
- Меньше обращений к DOM = выше скорость;
- UI моментально реагирует на изменения;
- Разработчику не нужно вручную синхронизировать DOM и данные;
Как обрабатывать события
React обрабатывает события похожим образом на обычный HTML и JavaScript, но с небольшими особенностями.
Вот пример кнопки, реагирующей на нажатие:
function ClickButton() {
function handleClick() {
alert('Кнопка была нажата!');
}
return <button onClick={handleClick}>Нажми на меня</button>;
}
В отличии от стандартного HTML, атрибуты событий пишутся с большой буквы (например, onClick
). Функция-обработчик не должна вызываться сразу — просто передается по имени.
Вы также можете передавать значения в обработчики:
function LikeButton({ postId }) {
function handleLike() {
// Выведет id поста
console.log('Лайк поста', postId);
}
return <button onClick={handleLike}>Лайк</button>;
}
Условный рендеринг
Иногда нужно показывать разные элементы в зависимости от состояния компонента.
Смотрите пример:
function AuthStatus({ isAuthenticated }) {
return (
<div>
{isAuthenticated ? (
<p>Вы вошли в систему</p>
) : (
<p>Пожалуйста, войдите в аккаунт</p>
)}
</div>
);
}
Вы можете использовать условный (тернарный) оператор, логическое "и" (&&
) или выражения внутри разметки.
Lists и key — отображение списков данных
Когда вы выводите список элементов, React требует указывать prop key
для каждого элемента — это помогает быстро обновлять список без лишних перерисовок. Обычно в качестве key используют уникальный идентификатор элемента.
Пример:
function TodoList({ tasks }) {
return (
<ul>
{tasks.map(task => (
<li key={task.id}>{task.text}</li>
))}
</ul>
);
}
- Передавайте уникальное значение, иначе React может допустить ошибки или снизить производительность.
Формы и управление вводом пользователя
React работает с формами чуть иначе, чем чистый HTML. Обычно значения инпутов хранятся в состоянии компонента.
Пример работы с текстовым полем:
import React, { useState } from 'react';
function NameForm() {
const [value, setValue] = useState('');
function handleChange(event) {
// Обновляем состояние при каждом изменении поля
setValue(event.target.value);
}
function handleSubmit(event) {
event.preventDefault(); // Останавливаем стандартную отправку формы
alert('Вы ввели: ' + value);
}
return (
<form onSubmit={handleSubmit}>
<label>
Имя:
<input type="text" value={value} onChange={handleChange} />
</label>
<button type="submit">Отправить</button>
</form>
);
}
Таким образом инпут становится "контролируемым" — все состояние остается под контролем компонента.
Использование хуков
Хуки — это функции, которые позволяют использовать состояние и другие возможности React в функциональных компонентах. Основные хуки:
useState
— управление состоянием;useEffect
— побочные эффекты, управление жизненным циклом;useContext
— доступ к контексту (передача данных без пропсов);useRef
— хранение изменяемых значений вне процесса рендеринга.
Давайте рассмотрим хук useRef
:
import React, { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus(); // Устанавливаем фокус на input
}
return (
<div>
<input ref={inputRef} type="text" placeholder="Нажмите на кнопку для фокуса" />
<button onClick={handleClick}>Фокус</button>
</div>
);
}
Здесь useRef хранит ссылку на DOM-элемент, и мы можем управлять этим элементом напрямую.
Стилизация компонентов
Есть несколько способов применить стили к компонентам в React:
- CSS-файлы: Классически подключаете внешний CSS.
- CSS-модули: Изолированные стили для каждого компонента.
- Inline-стили: Прямо через атрибут
style
. - Styled-components и Emotion: Использование CSS-in-JS — описание стилей прямо в JavaScript-коде.
Пример использования CSS-модуля:
// Button.module.css
.button {
background-color: #61dafb;
border: none;
color: white;
padding: 10px 20px;
cursor: pointer;
}
// Button.js
import styles from './Button.module.css';
function Button({ children }) {
return <button className={styles.button}>{children}</button>;
}
Это позволяет устранить конфликты имён стилей между компонентами.
Маршрутизация и SPA-приложения
Для создания одностраничных приложений (SPA) часто используют библиотеку react-router-dom
. Она позволяет показывать разные компоненты в зависимости от адреса страницы.
Вот минимальный пример:
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import HomePage from './HomePage';
import AboutPage from './AboutPage';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Главная</Link>
<Link to="/about">О нас</Link>
</nav>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
</Routes>
</BrowserRouter>
);
}
Теперь при переходе между /
и /about
будут меняться только нужные компоненты, страница не будет перезагружаться.
Архитектура приложения на React
- Папка компонентов (components): Содержит все многоразовые части UI.
- Папка страниц (pages): Хранит отдельные страницы или главные представления.
- Папка стилей (styles): CSS, SCSS, CSS-модули или другие подходы для стилизации.
- Папка утилит (utils): Хелперы, функции для работы с API и пр.
- Папка контекста (context): Если используется React Context для хранения состояния.
Это позволяет вам соблюдать чистую структуру и отделять логику, UI и сервисные функции.
Интеграция с внешними данными (API запросы)
Часто приложения получают данные с серверов через HTTP-запросы (например, с помощью fetch или axios).
Вот как можно реализовать загрузку данных:
import React, { useState, useEffect } from 'react';
function UsersList() {
const [users, setUsers] = useState([]);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json()) // парсим ответ
.then(data => {
setUsers(data); // сохраняем пользователей
setIsLoading(false); // снимаем флаг загрузки
});
}, []); // Пустой массив — запрос только при первом рендере
if (isLoading) {
return <p>Загрузка...</p>;
}
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
В этом примере мы сделали GET-запрос к бесплатному API и вывели пользователей на страницу.
Использование сторонних библиотек
React экосистема огромна. Для работы с формами часто используют Formik или React Hook Form, для управления состоянием — Redux или MobX, для анимаций — Framer Motion и так далее. Подключить библиотеку обычно достаточно одной команды в терминале и импорта нужных компонентов.
Тестирование компонентов
React поддерживает тестирование на разных уровнях — от юнит-тестов компонентов (с помощью Jest и React Testing Library) до интеграционных тестов всего приложения. Тесты проверяют, что интерфейс реагирует на действия пользователя, данные рендерятся правильно, обработчики событий работают корректно.
Пример простого теста:
// Counter.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';
test('увеличивает счётчик при нажатии', () => {
render(<Counter />);
fireEvent.click(screen.getByText('Плюс 1'));
expect(screen.getByText(/Текущее значение: 1/)).toBeInTheDocument();
});
Вы обеспечиваете уверенность в стабильной работе ваших компонентов при изменениях кода.
Заключение
Frontend-разработка на React — это мощный, гибкий и удобный способ создания современных веб-приложений. Благодаря компонентному подходу, виртуальному DOM, простоте взаимодействия с состоянием и мощной экосистеме, React стал де-факто стандартом в индустрии создания интерфейсов. Осваивая базовые концепции React — работу с компонентами, состоянием, хуками, обработкой событий — вы получаете универсальные инструменты для построения собственных динамичных, интерактивных и максимально эффективных приложений.
Frontend-разработка требует комплексных знаний. Для создания сложных приложений требуется умение управлять состоянием и роутингом. Курс Основы React, React Router и Redux Toolkit предоставляет комплексные знания и навыки для этого. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в основы React уже сегодня.
Частозадаваемые технические вопросы по теме статьи и ответы на них
Как правильно передать функцию из родительского в дочерний компонент?
Передайте функцию через props:
```jsx
function Parent() {
const handleChildClick = () => {
alert('Клик из дочернего компонента!');
};
return
function Child({ onClick }) { return ; } ``` Теперь при клике вызывается функция из родителя.
Почему компонент перерисовывается слишком часто?
Обычно из-за неаккуратного использования состояния или props. Проверьте:
- Нет ли изменения state без нужды;
- Передаются ли новые ссылочные значения (например, функции, объекты) каждый раз;
- Используйте
React.memo
для оптимизации, если компонент рендерит одно и то же при одинаковых props.
Как заранее узнать, что компонент размонтировался внутри useEffect?
Возвращайте функцию очистки (cleanup) из useEffect:
jsx
useEffect(() => {
// Ваш код
return () => {
// Этот код сработает при размонтировании компонента
};
}, []);
Это удобно для очистки таймеров, подписок на события и т.д.
Как использовать несколько состояний в одном компоненте?
Применяйте useState столько раз, сколько нужно:
jsx
const [name, setName] = useState('');
const [age, setAge] = useState(0);
Нет ограничений на количество useState в компоненте.
Как правильно получить доступ к DOM-элементу?
Используйте хук useRef и проп ref:
jsx
const myRef = useRef(null);
<input ref={myRef} />
// Теперь можно обращаться к myRef.current для доступа к DOM-элементу
Вы сможете получить доступ к DOM-узлу напрямую через myRef.current.
Постройте личный план изучения React до уровня Middle — бесплатно!
React — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Бесплатные лекции
Все гайды по React
Лучшие курсы по теме

React и Redux Toolkit
Антон Ларичев
TypeScript с нуля
Антон Ларичев