Что такое компонент в 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 (
<>
&lt;p&gt;Счётчик: {count}&lt;/p&gt;
&lt;button onClick={() =&gt; setCount(count + 1)}>+1&lt;/button&gt;
&lt;/&gt;
);
}

2. Классовые компоненты (Class Components)

До появления хуков состояние и методы жизненного цикла были доступны только в классовых компонентах. Сейчас используются реже, но по-прежнему поддерживаются.

Пример:

import React, { Component } from 'react';
class Welcome extends Component {
render() {
return &lt;h1&gt;Привет, {this.props.name}&lt;/h1&gt;;
}
}

Пример компонента с состоянием:

class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<>
&lt;p&gt;Счётчик: {this.state.count}&lt;/p&gt;
&lt;button onClick={this.increment}&gt;+1&lt;/button&gt;
&lt;/&gt;
);
}
}

Дополнительная классификация компонентов

3. Презентационные (или dumb) компоненты

Презентационные компоненты:

  • Отвечают только за внешний вид

  • Не имеют собственного состояния или имеют минимальное состояние

  • Получают все данные через пропсы

  • Чаще всего функциональные

Пример:

const UserCard = ({ name, avatar }) => (
&lt;div className="card"&gt;
&lt;img src={avatar} alt={name} /&gt;
&lt;h3&gt;{name}&lt;/h3&gt;
&lt;/div&gt;
);

4. Контейнерные (или smart) компоненты

Контейнерные компоненты:

  • Отвечают за логику и работу с данными (загрузка, фильтрация, обработка событий)

  • Могут содержать состояние

  • Используют презентационные компоненты внутри

Пример:

function UserContainer() {
const \[user, setUser\] = useState(null);
useEffect(() => {
fetch('/api/user').then(res => res.json()).then(setUser);
}, \[\]);
return user ? &lt;UserCard name={user.name} avatar={user.avatar} /&gt; : &lt;p&gt;Загрузка...&lt;/p&gt;;
}

5. Условные компоненты

Компоненты, которые рендерят разные элементы в зависимости от условий:

const Status = ({ online }) => (
&lt;div&gt;{online ? 'В сети' : 'Оффлайн'}&lt;/div&gt;
);

6. Компоненты высшего порядка (Higher-Order Components, HOC)

Функции, которые принимают компонент и возвращают новый компонент с расширенным функционалом:

function withLogger(WrappedComponent) {
return function(props) {
console.log('Параметры:', props);
return &lt;WrappedComponent {...props} /&gt;;
};
}

Использование:

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);
};
&lt;DataFetcher render={data =&gt; &lt;div&gt;{JSON.stringify(data)}&lt;/div&gt;} />

8. Контролируемые и неконтролируемые компоненты

  • Контролируемые компоненты — управляют значением через состояние React:
const Input = () => {
const \[value, setValue\] = useState('');
return &lt;input value={value} onChange={e =&gt; setValue(e.target.value)} />;
};
  • Неконтролируемые компоненты — управляют значением через DOM напрямую:
const Input = () => {
const inputRef = useRef();
const handleClick = () => {
console.log(inputRef.current.value);
};
return (
<>
&lt;input ref={inputRef} /&gt;
&lt;button onClick={handleClick}&gt;Печать&lt;/button&gt;
&lt;/&gt;
);
};

9. Переиспользуемые компоненты

Компоненты, которые написаны так, чтобы использоваться в разных местах с разными данными:

const Button = ({ children, onClick, variant = 'primary' }) => {
const className = variant === 'primary' ? 'btn-primary' : 'btn-secondary';
return &lt;button className={className} onClick={onClick}&gt;{children}&lt;/button&gt;;
};

10. Фрагменты (Fragments)

Компоненты, которые не создают дополнительных DOM-узлов:

return (
<>
&lt;h1&gt;Заголовок&lt;/h1&gt;
&lt;p&gt;Параграф&lt;/p&gt;
&lt;/&gt;
);

11. Порталы (Portals)

Позволяют рендерить компонент вне текущей иерархии DOM:

ReactDOM.createPortal(
&lt;Modal /&gt;,
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 &lt;h1&gt;Произошла ошибка&lt;/h1&gt;;
}
return this.props.children;
}
}