Функциональные и классовые компоненты — это два способа создания компонентов в React, но с ключевыми различиями:
| Характеристика | Функциональные | Классовые |
|---|---|---|
| Синтаксис | Проще и короче | Более многословный |
| Состояние | Хуки (useState) | this.state |
| Жизненный цикл | Хуки (useEffect) | Методы класса |
| Производительность | Лучше | Хуже |
| this | Не требуется | Требуется |
Современный подход:
В React есть два способа создания компонентов: функциональные и классовые. Хотя оба подхода создают компоненты, у них есть существенные различия в синтаксисе, возможностях и подходах к разработке.
Функциональные компоненты — это обычные JavaScript-функции, которые принимают props и возвращают JSX:
// Функциональный компонент
import { useState } from 'react';
function Welcome({ name }) {
const [count, setCount] = useState(0);
return (
<div>
<h1>Привет, {name}!</h1>
<p>Счетчик: {count}</p>
<button onClick={() => setCount(count + 1)}>
Увеличить
</button>
</div>
);
}Классовые компоненты — это ES6-классы, которые наследуются от React.Component:
// Классовый компонент
import { Component } from 'react';
class Welcome extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
render() {
return (
<div>
<h1>Привет, {this.props.name}!</h1>
<p>Счетчик: {this.state.count}</p>
<button onClick={() => this.setState({
count: this.state.count + 1
})}>
Увеличить
</button>
</div>
);
}
}Функциональные компоненты проще и короче:
// Функциональный компонент
function Greeting({ name }) {
return <h1>Привет, {name}!</h1>;
}Классовые компоненты более многословные:
// Классовый компонент
class Greeting extends Component {
render() {
return <h1>Привет, {this.props.name}!</h1>;
}
}Функциональные компоненты используют хуки:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Счетчик: {count}</p>
<button onClick={() => setCount(count + 1)}>
Увеличить
</button>
</div>
);
}Классовые компоненты используют this.state:
import { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
render() {
return (
<div>
<p>Счетчик: {this.state.count}</p>
<button onClick={() => this.setState({
count: this.state.count + 1
})}>
Увеличить
</button>
</div>
);
}
}Функциональные компоненты используют хуки:
import { useEffect, useState } from 'react';
function DataFetcher({ userId }) {
const [data, setData] = useState(null);
// Заменяет componentDidMount, componentDidUpdate, componentWillUnmount
useEffect(() => {
fetchData(userId).then(setData);
// Очистка (componentWillUnmount)
return () => {
// Отмена запросов, очистка таймеров
};
}, [userId]); // Зависимости
return <div>{data ? JSON.stringify(data) : 'Загрузка...'}</div>;
}Классовые компоненты используют методы жизненного цикла:
import { Component } from 'react';
class DataFetcher extends Component {
constructor(props) {
super(props);
this.state = { data: null };
}
// componentDidMount
componentDidMount() {
this.fetchData(this.props.userId);
}
// componentDidUpdate
componentDidUpdate(prevProps) {
if (prevProps.userId !== this.props.userId) {
this.fetchData(this.props.userId);
}
}
// componentWillUnmount
componentWillUnmount() {
// Отмена запросов, очистка таймеров
}
fetchData = async (userId) => {
const data = await fetchData(userId);
this.setState({ data });
}
render() {
return (
<div>
{this.state.data ? JSON.stringify(this.state.data) : 'Загрузка...'}
</div>
);
}
}Функциональные компоненты обычно быстрее:
// Функциональный компонент - меньше накладных расходов
function FastComponent({ data }) {
return (
<ul>
{data.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}Классовые компоненты имеют больше накладных расходов:
// Классовый компонент - больше накладных расходов
class SlowerComponent extends Component {
render() {
return (
<ul>
{this.props.data.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
}✅ Использовать всегда, когда возможно:
// Рекомендуемый подход
import { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchUser = async () => {
setLoading(true);
const userData = await fetch(`/api/users/${userId}`).then(r => r.json());
setUser(userData);
setLoading(false);
};
fetchUser();
}, [userId]);
if (loading) return <div>Загрузка...</div>;
if (!user) return <div>Пользователь не найден</div>;
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}❌ Использовать только при необходимости:
// Только для legacy-кода
import { Component } from 'react';
class LegacyUserProfile extends Component {
constructor(props) {
super(props);
this.state = { user: null, loading: true };
}
componentDidMount() {
this.fetchUser();
}
componentDidUpdate(prevProps) {
if (prevProps.userId !== this.props.userId) {
this.fetchUser();
}
}
fetchUser = async () => {
this.setState({ loading: true });
const userData = await fetch(`/api/users/${this.props.userId}`).then(r => r.json());
this.setState({ user: userData, loading: false });
}
render() {
if (this.state.loading) return <div>Загрузка...</div>;
if (!this.state.user) return <div>Пользователь не найден</div>;
return (
<div>
<h1>{this.state.user.name}</h1>
<p>{this.state.user.email}</p>
</div>
);
}
}Функциональный подход:
import { useState } from 'react';
function Toggle() {
const [isOn, setIsOn] = useState(false);
return (
<button onClick={() => setIsOn(!isOn)}>
{isOn ? 'ВКЛ' : 'ВЫКЛ'}
</button>
);
}Классовый подход:
import { Component } from 'react';
class Toggle extends Component {
constructor(props) {
super(props);
this.state = { isOn: false };
}
render() {
return (
<button onClick={() => this.setState({
isOn: !this.state.isOn
})}>
{this.state.isOn ? 'ВКЛ' : 'ВЫКЛ'}
</button>
);
}
}Функциональный подход:
import { useEffect, useState } from 'react';
function WindowSize() {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
const handleResize = () => {
setSize({
width: window.innerWidth,
height: window.innerHeight
});
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return (
<div>
<p>Ширина: {size.width}px</p>
<p>Высота: {size.height}px</p>
</div>
);
}Классовый подход:
import { Component } from 'react';
class WindowSize extends Component {
constructor(props) {
super(props);
this.state = {
width: window.innerWidth,
height: window.innerHeight
};
}
componentDidMount() {
window.addEventListener('resize', this.handleResize);
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
}
handleResize = () => {
this.setState({
width: window.innerWidth,
height: window.innerHeight
});
}
render() {
return (
<div>
<p>Ширина: {this.state.width}px</p>
<p>Высота: {this.state.height}px</p>
</div>
);
}
}Функциональные и классовые компоненты — два способа создания компонентов в React:
✅ Функциональные компоненты (современный подход):
❌ Классовые компоненты (устаревший подход):
Ключевые моменты:
Понимание разницы между этими подходами поможет выбрать правильный способ создания компонентов и обновить legacy-код при необходимости.
Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice, добавляйте сайт в закладки и совершенствуйтесь каждый день 💪