← Назад к вопросам

В чем разница между классовыми компонентами и компонентами на React Hooks?

2.0 Middle🔥 261 комментариев
#React#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между классовыми компонентами и React Hooks

Введение

Долгое время в React были только классовые компоненты. С версии 16.8 (2019) появились Hooks, которые позволяют использовать state и другие возможности React в функциональных компонентах.

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

Классовый компонент расширяет React.Component и имеет методы жизненного цикла:

import React from 'react';

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  componentDidMount() {
    console.log('Компонент загрузился');
  }

  componentDidUpdate(prevProps, prevState) {
    console.log('Компонент обновился');
  }

  componentWillUnmount() {
    console.log('Компонент будет удален');
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Увеличить
        </button>
      </div>
    );
  }
}

export default Counter;

Характеристики:

  • Используют this и методы жизненного цикла
  • State инициализируется в constructor
  • Методы жизненного цикла разделены по назначению
  • Требуют привязки методов (bind)

Функциональные компоненты с Hooks

С Hooks функциональные компоненты получили те же возможности:

import React, { useState, useEffect } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('Компонент загрузился или обновился');
    return () => {
      console.log('Cleanup перед обновлением или удалением');
    };
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Увеличить
      </button>
    </div>
  );
}

export default Counter;

Характеристики:

  • Простые функции
  • Нет this
  • useState для управления state
  • useEffect для побочных эффектов
  • Более читаемый код

Сравнительная таблица

АспектКлассовые компонентыHooks (функциональные)
Синтаксисclass Component extends React.Componentfunction Component()
Statethis.state, this.setState()useState()
Побочные эффектыcomponentDidMount, componentDidUpdateuseEffect()
ОчисткаcomponentWillUnmountreturn () => {} в useEffect
Контекстthis.contextuseContext()
ЧитаемостьБолее многословноБолее компактно
ПроизводительностьНормальнаяОбычно быстрее
Привязка методовНужен bind() или стрелкиНе требуется

Практические примеры

1. Управление Multiple State

Class Component:

class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: '',
      email: '',
      age: ''
    };
  }

  handleChange = (e) => {
    const { name, value } = e.target;
    this.setState({ [name]: value });
  };

  render() {
    return (
      <form>
        <input name="name" value={this.state.name} onChange={this.handleChange} />
        <input name="email" value={this.state.email} onChange={this.handleChange} />
        <input name="age" value={this.state.age} onChange={this.handleChange} />
      </form>
    );
  }
}

Hooks:

function Form() {
  const [form, setForm] = useState({ name: '', email: '', age: '' });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setForm({ ...form, [name]: value });
  };

  return (
    <form>
      <input name="name" value={form.name} onChange={handleChange} />
      <input name="email" value={form.email} onChange={handleChange} />
      <input name="age" value={form.age} onChange={handleChange} />
    </form>
  );
}

2. API запросы

Class Component:

class UserList extends React.Component {
  state = { users: [], loading: true, error: null };

  componentDidMount() {
    fetch('/api/users')
      .then(res => res.json())
      .then(users => this.setState({ users, loading: false }))
      .catch(error => this.setState({ error, loading: false }));
  }

  render() {
    const { users, loading, error } = this.state;
    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;
    return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
  }
}

Hooks:

function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch('/api/users')
      .then(res => res.json())
      .then(users => { setUsers(users); setLoading(false); })
      .catch(error => { setError(error); setLoading(false); });
  }, []);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

3. Фильтрация данных

Class Component:

class FilteredList extends React.Component {
  constructor(props) {
    super(props);
    this.state = { items: [1, 2, 3, 4, 5], filter: '' };
  }

  render() {
    const filtered = this.state.items.filter(
      i => i.toString().includes(this.state.filter)
    );
    return (
      <div>
        <input
          value={this.state.filter}
          onChange={e => this.setState({ filter: e.target.value })}
        />
        <ul>{filtered.map(i => <li key={i}>{i}</li>)}</ul>
      </div>
    );
  }
}

Hooks:

function FilteredList() {
  const [items] = useState([1, 2, 3, 4, 5]);
  const [filter, setFilter] = useState('');
  
  const filtered = useMemo(
    () => items.filter(i => i.toString().includes(filter)),
    [items, filter]
  );

  return (
    <div>
      <input value={filter} onChange={e => setFilter(e.target.value)} />
      <ul>{filtered.map(i => <li key={i}>{i}</li>)}</ul>
    </div>
  );
}

Кастомные Hooks

Hooks позволяют создавать переиспользуемую логику:

// Кастомный Hook для API запросов
function useApi(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(data => { setData(data); setLoading(false); })
      .catch(error => { setError(error); setLoading(false); });
  }, [url]);

  return { data, loading, error };
}

// Использование
function App() {
  const { data: users, loading, error } = useApi('/api/users');
  if (loading) return <div>Loading...</div>;
  return <div>{users?.map(u => <div key={u.id}>{u.name}</div>)}</div>;
}

В классовых компонентах аналогичная логика требовала использования HOC или render props.

Преимущества Hooks

  • Более компактный и читаемый код
  • Легче переиспользовать логику (кастомные Hooks)
  • Проще избежать проблем с this
  • Лучше оптимизируется бандлер
  • Нет необходимости в привязке методов

Когда использовать классовые компоненты

  • Error Boundaries (пока нет Hook'а для этого)
  • Наследование (не рекомендуется, но возможно)
  • Старый код (миграция не обязательна)

Современный подход

Сегодня React сообщество переходит на функциональные компоненты с Hooks, а классовые компоненты считаются устаревшим паттерном.

Выводы

Hooks предоставляют более удобный и современный способ написания React компонентов. Они делают код более читаемым, улучшают переиспользование логики и становятся стандартом в новых проектах. Классовые компоненты остаются поддерживаемыми, но не рекомендуются для новых разработок.