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

Как определить что является контейнером?

1.0 Junior🔥 131 комментариев
#Soft Skills и рабочие процессы

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

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

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

Определение контейнеров в React архитектуре

В React и современной архитектуре компонентов существует четкое разделение между контейнерами (Container Components, Smart Components) и представлениями (Presentational Components, Dumb Components). Понимание этого различия критично для масштабируемого приложения.

Основные признаки контейнера

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

  1. Содержит бизнес-логику - управляет состоянием, эффекты, API запросы
  2. Работает с данными - получает, трансформирует, передает данные
  3. Оборачивает другие компоненты - комбинирует несколько компонентов представления
  4. Редко отвечает за UI - минимальная разметка, основной фокус на логике
// КОНТЕЙНЕР - управляет логикой и состоянием
import { useEffect, useState } from react;
import UserProfile from ./UserProfile; // Presentational component

function UserProfileContainer({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchUser() {
      try {
        const response = await fetch(`/api/users/${userId}`);
        const data = await response.json();
        setUser(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    }

    fetchUser();
  }, [userId]);

  // Передает только необходимые props в presentational компонент
  return <UserProfile user={user} loading={loading} error={error} />;
}

export default UserProfileContainer;

Признаки Presentational компонента

// PRESENTATIONAL - только UI, получает данные через props
function UserProfile({ user, loading, error }) {
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  if (!user) return null;

  return (
    <div className="bg-surface-primary p-6 rounded-lg">
      <img src={user.avatar} alt={user.name} className="w-20 h-20 rounded-full" />
      <h1 className="text-2xl font-bold mt-4">{user.name}</h1>
      <p className="text-text-secondary">{user.email}</p>
    </div>
  );
}

export default UserProfile;

Паттерны контейнеров

1. Container Component (старый подход)

function CommentsContainer({ postId }) {
  const [comments, setComments] = useState([]);
  const [filter, setFilter] = useState(all);

  const filteredComments = comments.filter(c => 
    filter === all || c.status === filter
  );

  return (
    <CommentsPresentation
      comments={filteredComments}
      filter={filter}
      onFilterChange={setFilter}
    />
  );
}

2. Custom Hook (современный подход)

Вместо оборачивания в компонент-контейнер, используй кастомный хук:

// Логика в хуке
function useComments(postId) {
  const [comments, setComments] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetch() {
      try {
        const data = await api.getComments(postId);
        setComments(data);
      } finally {
        setLoading(false);
      }
    }
    fetch();
  }, [postId]);

  return { comments, loading };
}

// Компонент использует хук
function Comments({ postId }) {
  const { comments, loading } = useComments(postId);

  if (loading) return <LoadingSpinner />;
  return <CommentsList comments={comments} />;
}

Как определить тип компонента на практике

// Контейнер: использует useState, useEffect, useContext, useReducer
function OrdersContainer() {
  const [orders, setOrders] = useState([]);
  const { userId } = useContext(AuthContext);

  useEffect(() => {
    // логика загрузки
  }, [userId]);

  return <OrdersList orders={orders} />;
}

// Presentational: чистые функции, только props
function OrdersList({ orders }) {
  return (
    <div className="space-y-4">
      {orders.map(order => (
        <OrderCard key={order.id} order={order} />
      ))}
    </div>
  );
}

Преимущества разделения

  1. Переиспользование логики - один контейнер может использовать разные presentational компоненты
  2. Простое тестирование - presentational компоненты тестируются как чистые функции
  3. Отделение логики от UI - изменение дизайна не требует изменения логики
  4. Масштабируемость - четкая структура упрощает работу в большой команде
  5. Понятность кода - явно видно, где логика, где UI

Modern React подход

В современном React с хуками граница между контейнером и presentational стирается. Однако принцип остается:

  • Выноси логику в кастомные хуки
  • Компоненты остаются максимально простыми
  • Передавай только необходимые данные через props

Это делает код более модульным, тестируемым и поддерживаемым.