Что такое компонент в React? Какие бывают типы компонентов?
Компонент в React — это переиспользуемая изолированная часть пользовательского интерфейса, которая определяет, как должен выглядеть интерфейс и как он должен себя вести. Компоненты позволяют разбивать интерфейс на независимые части, каждая из которых управляет своим собственным состоянием и может быть повторно использована.
React-компонент по сути — это функция (или раньше — класс), которая возвращает JSX (JavaScript XML) — синтаксис, похожий на HTML, описывающий, что должно отображаться на экране.
Типы компонентов в React
1. Функциональные компоненты (Function Components)
Функциональные компоненты — это JavaScript-функции, которые принимают пропсы (входные данные) и возвращают JSX. С 2019 года (после появления React Hooks) функциональные компоненты стали основным способом написания компонентов.
Простой пример:
function Welcome(props) {
return <h1>Привет, {props.name}</h1>;
}
или через стрелочную функцию:
const Welcome = ({ name }) => <h1>Привет, {name}</h1>;
Функциональные компоненты могут использовать хуки (useState, useEffect, и т.д.) для управления состоянием и побочными эффектами:
import { useState } from 'react';
function Counter() {
const \[count, setCount\] = useState(0);
return (
<>
<p>Счётчик: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</>
);
}
2. Классовые компоненты (Class Components)
До появления хуков состояние и методы жизненного цикла были доступны только в классовых компонентах. Сейчас используются реже, но по-прежнему поддерживаются.
Пример:
import React, { Component } from 'react';
class Welcome extends Component {
render() {
return <h1>Привет, {this.props.name}</h1>;
}
}
Пример компонента с состоянием:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<>
<p>Счётчик: {this.state.count}</p>
<button onClick={this.increment}>+1</button>
</>
);
}
}
Дополнительная классификация компонентов
3. Презентационные (или dumb) компоненты
Презентационные компоненты:
-
Отвечают только за внешний вид
-
Не имеют собственного состояния или имеют минимальное состояние
-
Получают все данные через пропсы
-
Чаще всего функциональные
Пример:
const UserCard = ({ name, avatar }) => (
<div className="card">
<img src={avatar} alt={name} />
<h3>{name}</h3>
</div>
);
4. Контейнерные (или smart) компоненты
Контейнерные компоненты:
-
Отвечают за логику и работу с данными (загрузка, фильтрация, обработка событий)
-
Могут содержать состояние
-
Используют презентационные компоненты внутри
Пример:
function UserContainer() {
const \[user, setUser\] = useState(null);
useEffect(() => {
fetch('/api/user').then(res => res.json()).then(setUser);
}, \[\]);
return user ? <UserCard name={user.name} avatar={user.avatar} /> : <p>Загрузка...</p>;
}
5. Условные компоненты
Компоненты, которые рендерят разные элементы в зависимости от условий:
const Status = ({ online }) => (
<div>{online ? 'В сети' : 'Оффлайн'}</div>
);
6. Компоненты высшего порядка (Higher-Order Components, HOC)
Функции, которые принимают компонент и возвращают новый компонент с расширенным функционалом:
function withLogger(WrappedComponent) {
return function(props) {
console.log('Параметры:', props);
return <WrappedComponent {...props} />;
};
}
Использование:
const EnhancedComponent = withLogger(MyComponent);
7. Компоненты-рендер-пропы
Компоненты, которые принимают функцию как проп и вызывают её для рендеринга:
const DataFetcher = ({ render }) => {
const \[data, setData\] = useState(null);
useEffect(() => {
fetch('/api/data').then(res => res.json()).then(setData);
}, \[\]);
return render(data);
};
<DataFetcher render={data => <div>{JSON.stringify(data)}</div>} />
8. Контролируемые и неконтролируемые компоненты
- Контролируемые компоненты — управляют значением через состояние React:
const Input = () => {
const \[value, setValue\] = useState('');
return <input value={value} onChange={e => setValue(e.target.value)} />;
};
- Неконтролируемые компоненты — управляют значением через DOM напрямую:
const Input = () => {
const inputRef = useRef();
const handleClick = () => {
console.log(inputRef.current.value);
};
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>Печать</button>
</>
);
};
9. Переиспользуемые компоненты
Компоненты, которые написаны так, чтобы использоваться в разных местах с разными данными:
const Button = ({ children, onClick, variant = 'primary' }) => {
const className = variant === 'primary' ? 'btn-primary' : 'btn-secondary';
return <button className={className} onClick={onClick}>{children}</button>;
};
10. Фрагменты (Fragments)
Компоненты, которые не создают дополнительных DOM-узлов:
return (
<>
<h1>Заголовок</h1>
<p>Параграф</p>
</>
);
11. Порталы (Portals)
Позволяют рендерить компонент вне текущей иерархии DOM:
ReactDOM.createPortal(
<Modal />,
document.getElementById('modal-root')
);
12. Error Boundary (Границы ошибок)
Компоненты-классы, которые отлавливают ошибки в дочерних компонентах:
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
render() {
if (this.state.hasError) {
return <h1>Произошла ошибка</h1>;
}
return this.props.children;
}
}