Привет! Если ты начинаешь изучать веб-разработку, то наверняка слышал о React. Этот фреймворк стал стандартом индустрии и используется в тысячах проектов по всему миру. В этой статье разберем основные концепции React: компоненты, состояние, пропсы и хуки - всё, что нужно знать для начала работы.
Что такое React и почему он стал стандартом
React - это JavaScript-библиотека для создания пользовательских интерфейсов. Её главная идея заключается в компонентном подходе: сложный интерфейс разбивается на маленькие, переиспользуемые части. Это упрощает разработку, тестирование и поддержку кода.
React появился в 2013 году и быстро завоевал популярность благодаря своей простоте и эффективности. Многие крупные компании используют React в своих проектах. Если ты уже знаком с концепцией виртуального DOM, то знаешь, что React активно использует её для оптимизации производительности.
Компоненты в React: основа архитектуры
Компонент - это строительный блок React-приложения. Каждый компонент отвечает за отображение части интерфейса и может содержать свою логику. Компоненты можно сравнить с LEGO-кирпичиками: из них собирают сложные структуры.
В React есть два типа компонентов: функциональные и классовые. Функциональные компоненты сейчас являются стандартом, а классовые постепенно уходят в прошлое. Рассмотрим пример функционального компонента:
function Welcome() {
return <h1>Привет, мир!</h1>;
}Этот компонент просто выводит заголовок. Но настоящая сила React проявляется, когда компоненты принимают данные и содержат состояние. Компоненты могут быть переиспользуемыми: один и тот же компонент можно использовать в разных частях приложения с разными данными.
Состояние (state) и его управление
Состояние - это данные, которые могут меняться в процессе работы компонента. Представь счетчик кликов: его значение изменяется каждый раз, когда пользователь нажимает кнопку. Это значение - состояние компонента.
Для работы с состоянием в функциональных компонентах используется хук useState. Давайте создадим простой счетчик:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Вы кликнули {count} раз</p>
<button onClick={() => setCount(count + 1)}>
Нажми меня
</button>
</div>
);
}useState возвращает массив из двух элементов: текущее значение состояния и функцию для его обновления. Когда мы вызываем setCount, React перерисовывает компонент с новым значением.
Важно понимать, что состояние в React неизменяемое. Мы не можем просто написать count = count + 1 - нужно использовать функцию setCount. Это помогает React отслеживать изменения и оптимизировать перерисовку.
Пропсы: передача данных между компонентами
Пропсы (properties) - это способ передачи данных от родительского компонента к дочернему. Пропсы подобны аргументам функции: они передаются компоненту при его создании и используются внутри него.
Создадим компонент, который приветствует пользователя по имени:
function Greeting(props) {
return <h1>Привет, {props.name}!</h1>;
}
function App() {
return (
<div>
<Greeting name="Иван" />
<Greeting name="Мария" />
</div>
);
}Здесь мы передаем проп name в компонент Greeting. Можно использовать деструктуризацию для более чистого кода:
function Greeting({ name }) {
return <h1>Привет, {name}!</h1>;
}Пропсы неизменяемы - компонент не может изменить свои пропсы. Если данные должны меняться, используйте состояние.
Хуки: современный способ работы с состоянием и эффектами
Хуки - это функции, которые позволяют использовать состояние и другие возможности React в функциональных компонентах. Появившись в React 16.8, они полностью изменили подход к написанию компонентов. До хуков для работы с состоянием приходилось использовать классовые компоненты, что делало код более громоздким и сложным для понимания.
Мы уже рассмотрели useState - самый базовый хук. Другой важный хук - useEffect. Он позволяет выполнять побочные эффекты: загрузку данных, подписку на события, изменение DOM и другие операции. useEffect заменяет методы жизненного цикла классовых компонентов: componentDidMount, componentDidUpdate и componentWillUnmount.
Вот пример компонента, который загружает данные из API:
import { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchUser() {
try {
const response = await fetch(`/api/users/${userId}`);
const data = await response.json();
setUser(data);
} catch (error) {
console.error('Ошибка загрузки:', error);
} finally {
setLoading(false);
}
}
fetchUser();
}, [userId]);
if (loading) {
return <p>Загрузка...</p>;
}
if (!user) {
return <p>Пользователь не найден</p>;
}
return (
<div>
<h2>{user.name}</h2>
<p>Email: {user.email}</p>
</div>
);
}useEffect принимает два аргумента: функцию с эффектом и массив зависимостей. Эффект выполняется после каждого рендера, но если указать массив зависимостей, React будет запускать эффект только при изменении этих значений. Если передать пустой массив [], эффект выполнится только один раз при монтировании компонента.
Полезно знать, что useEffect может возвращать функцию очистки. Она вызывается при размонтировании компонента или перед повторным выполнением эффекта. Это полезно для отмены подписок, очистки таймеров и других операций.
useEffect(() => {
const timer = setInterval(() => {
console.log('Тик-так');
}, 1000);
return () => {
clearInterval(timer);
};
}, []);Хуки нужно вызывать только на верхнем уровне компонента, не внутри циклов, условий или вложенных функций. Это правило обеспечивает, что хуки вызываются в одном и том же порядке при каждом рендере. React полагается на этот порядок для правильной работы хуков.
Оптимизация производительности с помощью мемоизации
React предоставляет несколько способов оптимизации производительности компонентов. Один из них - хук useMemo, который кэширует результат вычислений. Это полезно для дорогих вычислений, которые не нужно повторять при каждом рендере.
import { useMemo } from 'react';
function ExpensiveCalculation({ numbers }) {
const sum = useMemo(() => {
console.log('Вычисление суммы...');
return numbers.reduce((acc, num) => acc + num, 0);
}, [numbers]);
return <p>Сумма: {sum}</p>;
}Другой полезный хук - useCallback. Он мемоизирует функцию, предотвращая её пересоздание при каждом рендере. Это важно, когда функция передается как проп дочернему компоненту, который оптимизирован с помощью React.memo.
import { useCallback, useState } from 'react';
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Клик!');
}, []);
return (
<div>
<button onClick={handleClick}>Нажми</button>
<p>Счетчик: {count}</p>
<button onClick={() => setCount(count + 1)}>Увеличить</button>
</div>
);
}Правила работы с React
При разработке на React важно соблюдать несколько правил. Во-первых, компоненты должны быть чистыми функциями: одинаковые входные данные должны давать одинаковый результат. Не используйте глобальные переменные или мутацию аргументов.
Во-вторых, сохраняйте компоненты маленькими и фокусированными. Один компонент должен отвечать за одну функцию. Это облегчает тестирование и повторное использование. Если компонент становится слишком большим, разделите его на несколько более мелких.
В-третьих, используйте propTypes или TypeScript для проверки типов пропсов. Это помогает выявить ошибки на ранних этапах разработки и улучшает документацию кода.
import PropTypes from 'prop-types';
function Button({ text, onClick }) {
return <button onClick={onClick}>{text}</button>;
}
Button.propTypes = {
text: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
};Заключение
React - мощный инструмент для создания интерактивных интерфейсов. Основные концепции, которые мы рассмотрели - компоненты, состояние, пропсы и хуки - это фундамент, на котором строится любое React-приложение. Начинай с простых компонентов, постепенно добавляя сложность и функциональность.
В следующих статьях мы изучим Nest.js, чтобы ты мог создавать полноценные веб-приложения как с фронтендом, так и с бэкендом.
📩 Подпишитесь на блог, чтобы не пропустить новые статьи о веб-разработке.



Обязательные поля помечены *