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

По какому принципу разбиваешь компоненты

1.2 Junior🔥 162 комментариев
#JavaScript Core

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

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

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

По какому принципу разбиваешь компоненты?

Разбивка компонентов на части — это один из самых важных навыков в современной фронтенд-разработке. Правильная структуризация компонентов влияет на переиспользуемость кода, читаемость и масштабируемость приложения.

Основной принцип: Single Responsibility Principle (SRP)

Первый и главный принцип — каждый компонент должен отвечать за одну вещь:

// Плохо - компонент делает слишком много
function UserProfile() {
  return (
    <div>
      <h1>User Profile</h1>
      <input placeholder="Name" />
      <input placeholder="Email" />
      <button>Save</button>
      <div>User stats</div>
      <div>Recent activity</div>
    </div>
  );
}

// Хорошо - разделены ответственности
function UserProfile({ user }) {
  return (
    <div>
      <UserHeader user={user} />
      <UserForm user={user} />
      <UserStats user={user} />
      <UserActivity user={user} />
    </div>
  );
}

Принципы разбивки

1. По функциональной площадке (Feature-based) Группируй компоненты по логическим фичам:

components/
  auth/
    LoginForm.tsx
    RegisterForm.tsx
    LogoutButton.tsx
  comments/
    CommentList.tsx
    CommentItem.tsx
    CommentForm.tsx
  profile/
    ProfileHeader.tsx
    ProfileEdit.tsx
    ProfileStats.tsx

Это помогает быстро найти все компоненты, относящиеся к конкретной фиче.

2. По уровню переиспользуемости Разбивай компоненты по уровню абстракции:

components/
  ui/                    # Базовые UI-компоненты
    Button.tsx
    Input.tsx
    Card.tsx
    Modal.tsx
  layout/               # Макет страницы
    Header.tsx
    Footer.tsx
    Sidebar.tsx
  sections/             # Секции лендинга
    HeroSection.tsx
    FeaturesSection.tsx
  {feature}/            # Компоненты конкретных фич
    QuestionList.tsx
    QuestionCard.tsx

3. По данным (Smart vs Presentational) Разделяй логику и представление:

// Smart component (контейнер) - работает с данными
export function UserProfileContainer({ userId }) {
  const [user, setUser] = useState(null);
  
  useEffect(() => {
    fetchUser(userId).then(setUser);
  }, [userId]);
  
  return <UserProfilePresentation user={user} />;
}

// Presentational component - только UI
function UserProfilePresentation({ user }) {
  return (
    <div className="profile">
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

Как я определяю, нужно ли разделить компонент?

Вопросы для себя:

  1. Размер — компонент > 300 строк? Вероятно, нужна разбивка
  2. Ответственность — компонент делает 2+ независимых вещи? Раздели
  3. Переиспользуемость — часть логики нужна в других местах? Выдели в отдельный компонент
  4. Тестируемость — сложно тестировать компонент целиком? Разбей на части
  5. Props — много props (> 10)? Возможно, это несколько компонентов
// Признаки, что нужна разбивка
const ComplexComponent = ({
  userName,
  userEmail,
  userAvatar,
  userBio,
  postTitle,
  postContent,
  postDate,
  comments,
  commentCount,
  isLoading,
  isError,
  onSave,
  onDelete,
  // ... слишком много props
}) => {
  // ...
};

Практический пример разбивки

Исходный монолитный компонент:

function ArticleWithComments({ articleId }) {
  const [article, setArticle] = useState(null);
  const [comments, setComments] = useState([]);
  const [newComment, setNewComment] = useState('');
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    // Загрузка статьи
    // Загрузка комментариев
  }, [articleId]);
  
  // Слишком много логики...
}

После разбивки:

// Контейнер управляет данными
function ArticleWithComments({ articleId }) {
  const { article, loading } = useArticle(articleId);
  const { comments, addComment } = useComments(articleId);
  
  return (
    <>
      <ArticleView article={article} />
      <CommentsSection comments={comments} onAdd={addComment} />
    </>
  );
}

// Компоненты только отображают
function ArticleView({ article }) {
  return <article>{/* UI */}</article>;
}

function CommentsSection({ comments, onAdd }) {
  return <section>{/* UI */}</section>;
}

Правило большого пальца (Rule of Three)

Если код повторяется 3 раза — выдели в компонент:

  • 1 раз: OK, не выделяй
  • 2 раза: можно выделить для читаемости
  • 3+ раза: ОБЯЗАТЕЛЬНО выдели в компонент

Антипаттерны, которых избегаю

Слишком глубокая вложенность:

// Плохо
<UserContainer>
  <UserWrapper>
    <UserInnerWrapper>
      <UserContent />
    </UserInnerWrapper>
  </UserWrapper>
</UserContainer>

Компонент-свалка:

// Плохо - компонент User.tsx делает всё
// использовать User everywhere
// вместо специализированных компонентов

Props drilling (передача props на много уровней вниз):

// Плохо
<Parent user={user}>
  <Child user={user}>
    <GrandChild user={user}>
      {user.name}
    </GrandChild>
  </Child>
</Parent>

// Хорошо - использовать Context или hooks

Мой процесс разбивки

  1. Пишу весь функционал в одном компоненте
  2. Определяю независимые части (по функциям, по UI блокам)
  3. Выделяю частые повторения в отдельные компоненты
  4. Разделяю логику от представления (custom hooks)
  5. Тестирую каждый компонент отдельно
  6. Рефакторю для улучшения читаемости

Заключение

Правильная разбивка компонентов — это баланс между гибкостью и простотой. Следуй принципам SRP и SOLID, и твой код будет легче поддерживать, тестировать и расширять. Помни: лучше иметь много маленьких компонентов, чем несколько огромных.

По какому принципу разбиваешь компоненты | PrepBro