Именование компонентов в React: соглашения и лучшие практики

16 июня 2026
Автор

Олег Марков

Именование компонентов в React

Именование — одна из тех вещей, которые кажутся тривиальными, но на практике сильно влияют на читаемость, поддерживаемость и масштабируемость проекта. В React сложились устойчивые соглашения об именовании, которых придерживается подавляющее большинство команд. В этой статье разберём все аспекты именования: от компонентов до CSS-классов.

Почему именование важно

Представьте, что вы открываете незнакомый компонент в большом проекте. Если он называется D, Component1 или Handler, вы тратите время на чтение кода, чтобы понять его назначение. Если компонент называется UserProfileCard или PaymentFormModal, назначение очевидно с первого взгляда.

Хорошее именование:

  • Сокращает время onboarding новых разработчиков
  • Упрощает поиск компонентов в проекте
  • Снижает количество ошибок из-за неверного понимания назначения

Компоненты: PascalCase

Все React-компоненты именуются в PascalCase (каждое слово с заглавной буквы). Это не просто договорённость — React использует регистр первой буквы для различения компонентов и HTML-элементов.

// ✅ Правильно
function UserProfile() {
  return <div>...</div>;
}

// ✅ Правильно
const OrderSummaryCard = () => {
  return <div>...</div>;
};

// ❌ Неправильно — React воспримет как HTML-элемент
function userProfile() {
  return <div>...</div>;
}

// ❌ Неправильно
const order_summary = () => {
  return <div>...</div>;
};

Принцип одной ответственности в именовании

Название компонента должно отражать, что именно он делает или что отображает. Избегайте общих слов вроде Component, Block, Item без уточнения:

// ❌ Слишком общее
function Block() { ... }
function Item() { ... }
function Component() { ... }

// ✅ Конкретное и описательное
function ProductCard() { ... }
function CartItem() { ... }
function NavigationMenu() { ... }

Составные имена

Когда компонент является частью большей сущности, используйте составные имена:

// Группа компонентов для формы авторизации
function AuthForm() { ... }
function AuthFormInput() { ... }
function AuthFormSubmitButton() { ... }
function AuthFormErrorMessage() { ... }

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

Именование файлов и директорий

Существует два популярных подхода к именованию файлов:

Подход 1: PascalCase (совпадает с именем компонента)

components/
  UserProfile.tsx
  OrderSummaryCard.tsx
  NavigationMenu.tsx

Преимущество: сразу видно, что файл содержит компонент. Легко найти файл по имени компонента.

Подход 2: kebab-case

components/
  user-profile.tsx
  order-summary-card.tsx
  navigation-menu.tsx

Преимущество: избегает проблем с регистром на разных ОС (Linux чувствителен к регистру, macOS — нет).

Структура директорий для компонента

Для сложных компонентов создавайте директорию:

components/
  UserProfile/
    index.tsx          // Основной компонент
    UserProfile.tsx    // Или так (если используете именованный файл)
    UserAvatar.tsx     // Дочерние компоненты
    useUserProfile.ts  // Хук компонента
    types.ts           // Типы
    styles.module.css  // Стили (если CSS Modules)

Именование хуков

Все кастомные хуки обязательно должны начинаться с use. Это требование React — только так линтер и React DevTools могут отличить хук от обычной функции.

// ✅ Правильно
function useUserData(userId: string) {
  const [user, setUser] = useState(null);
  // ...
  return { user };
}

function useDebounce<T>(value: T, delay: number): T {
  // ...
}

function useLocalStorage<T>(key: string, initialValue: T) {
  // ...
}

// ❌ Неправильно — React не распознает как хук
function getUserData(userId: string) { ... }
function debounce<T>(value: T, delay: number) { ... }

Принципы именования хуков

Хорошее имя хука описывает, что он предоставляет или делает:

// Описывает что возвращает
useUserProfile()     // возвращает данные профиля
useFormValidation()  // возвращает состояние валидации
useWindowSize()      // возвращает размер окна

// Описывает поведение
useToggle()          // переключает булевое значение
useDebounce()        // откладывает выполнение
usePrevious()        // хранит предыдущее значение

Именование пропсов

Булевые пропсы

Булевые пропсы принято именовать с префиксом is, has, can, should:

interface ButtonProps {
  isDisabled?: boolean;   // состояние
  isLoading?: boolean;    // состояние загрузки
  hasError?: boolean;     // наличие ошибки
  canSubmit?: boolean;    // возможность действия
  shouldAnimate?: boolean; // поведение
}

// Использование — читается как утверждение
<Button isDisabled={!isValid} isLoading={submitting} />

Обработчики событий

Обработчики событий именуются с префиксом on:

interface CardProps {
  onClose: () => void;
  onClick: (id: string) => void;
  onDataLoad: (data: User[]) => void;
  onChange: (value: string) => void;
}

// Внутри компонента функции-обработчики именуются с handle
function UserCard({ onClose, onClick }: CardProps) {
  const handleClose = () => {
    // внутренняя логика
    onClose();
  };

  const handleClick = () => {
    onClick(user.id);
  };

  return (
    <div onClick={handleClick}>
      <button onClick={handleClose}>×</button>
    </div>
  );
}

Рендер-пропсы и children

interface ListProps<T> {
  items: T[];
  renderItem: (item: T) => React.ReactNode;  // prefix render
  renderEmpty?: () => React.ReactNode;
  children?: React.ReactNode;
}

Именование переменных состояния

Для useState принято именовать пару [значение, setЗначение]:

// ✅ Стандартное именование
const [isOpen, setIsOpen] = useState(false);
const [userName, setUserName] = useState('');
const [items, setItems] = useState<Item[]>([]);
const [selectedId, setSelectedId] = useState<string | null>(null);

// ❌ Неудобно читать
const [value1, setValue1] = useState(false);
const [x, setX] = useState('');

Именование констант и перечислений

Глобальные константы и значения перечислений именуются в UPPER_SNAKE_CASE:

// Константы
const MAX_RETRY_COUNT = 3;
const API_BASE_URL = 'https://api.example.com';
const DEFAULT_PAGE_SIZE = 20;

// Enum — значения в PascalCase или UPPER_SNAKE_CASE
enum UserRole {
  Admin = 'ADMIN',
  Editor = 'EDITOR',
  Viewer = 'VIEWER',
}

// Объект-константа как альтернатива enum
const STATUS = {
  IDLE: 'idle',
  LOADING: 'loading',
  SUCCESS: 'success',
  ERROR: 'error',
} as const;

type Status = typeof STATUS[keyof typeof STATUS];

Именование типов и интерфейсов

// Интерфейсы — PascalCase, без префикса I (современная практика)
interface UserProfile {
  id: string;
  name: string;
  email: string;
}

// Типы — PascalCase
type ButtonVariant = 'primary' | 'secondary' | 'danger';
type UserId = string;

// Дженерики — краткое имя или описательное
type ApiResponse<T> = {
  data: T;
  error: string | null;
};

// Пропсы компонента — ComponentNameProps
interface UserCardProps {
  user: UserProfile;
  onEdit: (id: string) => void;
}

Типичные ошибки именования

Аббревиатуры и сокращения

Избегайте неочевидных сокращений:

// ❌ Непонятно
function UsrPrfl() { ... }
function PrdCrd() { ... }
const usr = getUser();

// ✅ Понятно
function UserProfile() { ... }
function ProductCard() { ... }
const user = getUser();

Исключение — общепринятые аббревиатуры: URL, ID, API, HTML, CSS.

// ✅ Общепринятые аббревиатуры — ок
function getUserById(id: string) { ... }
const apiUrl = 'https://...';
interface HTMLElementProps { ... }

Слишком длинные имена

// ❌ Слишком длинно
function TheMainUserProfilePageHeaderNavigationMenuComponent() { ... }

// ✅ Достаточно конкретно
function ProfileHeader() { ... }
function ProfileNavigation() { ... }

Бессмысленные суффиксы

// ❌ Суффикс ничего не добавляет
function UserProfileHelper() { ... }
function OrderManager() { ... }
const dataObject = { ... };

// ✅ Если нужно уточнить — уточняйте конкретно
function formatUserProfile() { ... }
function useOrderState() { ... }
const orderData = { ... };

Соглашения для CSS и стилизации

При использовании CSS Modules:

// styles.module.css — kebab-case классы
.user-profile { ... }
.user-profile__avatar { ... }
.user-profile--active { ... }

// В компоненте
import styles from './styles.module.css';

function UserProfile() {
  return (
    <div className={styles['user-profile']}>
      <img className={styles['user-profile__avatar']} />
    </div>
  );
}

При использовании Tailwind или styled-components именование следует тем же принципам PascalCase для компонентов.

Итоги

Подведём ключевые правила именования в React:

Сущность Стиль Пример
Компоненты PascalCase UserProfile
Файлы компонентов PascalCase или kebab-case UserProfile.tsx
Хуки camelCase с use useUserData
Пропсы-обработчики camelCase с on onClick
Внутренние обработчики camelCase с handle handleClick
Булевые пропсы camelCase с is/has/can isDisabled
Константы UPPERSNAKECASE MAX_COUNT
Типы/интерфейсы PascalCase UserProfileProps
Состояние camelCase + set [count, setCount]

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

Стрелочка влевоЧастичное применение: как создавать компоненты без лишнего кодаЛенивая загрузка: как ускорить React-приложение в разыСтрелочка вправо

Постройте личный план изучения React до уровня Middle — бесплатно!

React — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по React

Uncontrolled Components: когда DOM управляет даннымиБезопасность в React: защита от XSS, CSRF и утечек данныхRender Props: гибкое управление рендерингом в ReactРефакторинг React-кода: техники и лучшие практикиПрофилирование React: как найти и устранить узкие местаЧастичное применение: как создавать компоненты без лишнего кодаИменование компонентов в React: соглашения и лучшие практикиЛенивая загрузка: как ускорить React-приложение в разыHOC в React: мастерство композиции компонентовuseMemo: как спасти производительность от тяжелых вычисленийError Boundaries: создаем надежные React-приложенияКонтролируемые компоненты в React: полный контроль над формамиCompound Components в React: создаем гибкие компоненты с мощным APIДокументирование компонентов в React: Storybook, JSDoc и READMEКомпозиция компонентов в React: строим гибкие интерфейсыКомментирование кода в React: когда и как писать комментарииCode Splitting в React: как уменьшить бандл и ускорить загрузку приложенияАсинхронные компоненты в React: новый стандарт работы с даннымиДоступность (a11y) в React: ARIA, семантика и клавиатурная навигация
Zustand — управление состоянием в ReactZod - валидация с TypeScriptYup - валидация схемXState - конечные автоматыТемизация в ReactТестирование хуковTailwind CSS с ReactSWR - библиотека для запросовStyled Components — стилизация через JSStorybook - документация компонентовSnapshots тестированиеRTK Query - работа с APIRedux Toolkit - современный ReduxRecoil — библиотека управления состоянием от FacebookВиртуализация списков с react-window: как отображать тысячи элементов без лаговReact Toastify - уведомления в ReactReact Testing LibraryСоздание таблиц в React гайд по react-tableReact Spring - анимацииРабота с формами и селектами в ReactReact Query (TanStack Query) - работа с серверомПлагины в React что это и как их использоватьReact PDF - работа с PDF файламиОбзор популярных библиотек для ReactReact Icons - библиотека иконок для ReactReact Hook Form — валидация форм в ReactReact Dropzone — загрузка файловПодключение Bootstrap к React-приложениюReact Beautiful DnD - перетаскивание элементовАнимация при монтировании компонентов в ReactМокирование APIMobX — реактивное управление состоянием в ReactМикрофронтенды с React (micro-frontends)Загрузка и индикаторыАнимация списков в ReactJotai - атомарное состояниеБесконечная прокруткаFramer Motion - библиотека анимацийEmotion — библиотека CSS-in-JSДинамические стили в ReactE2E тестирование с CypressCSSTransition - переходыCSS-in-JS — плюсы и минусыКонтекст vs Redux — когда что использоватьИспользование Chart.js в ReactAxios с ReactТестирование асинхронных компонентовОбработка ошибок API
useState в React что это и как использоватьuseTransition - плавные переходы между состояниямиuseSyncExternalStore — работа с внешними сторамиuseRef в React — создание ссылок на DOM и значенияuseOptimistic — оптимистичные обновления UIuseLayoutEffect в React — эффект до отрисовкиuseInsertionEffect — внедрение стилей до мутаций DOMuseImperativeHandle в React — настройка ref дочернего компонентаuseId — генерация уникальных идентификаторовuseFormStatus - отслеживание статуса отправки формыuseDeferredValue — отложенное обновление состоянияuseDebugValue — отладка кастомных хуковuseCallback в React — мемоизация функцийuseReducer — альтернатива useState для сложной логикиuseMemo в React: как и когда оптимизировать тяжелые вычисленияuseEffect в React что это и как использоватьuseContext — работа с контекстом в ReactuseCallback в React — мемоизация функций и оптимизация ре-рендеровuseActionState в React 19Оптимизация рендеринга в React: от теории к глубокой практикеЧто такое useRef и как его применять в ReactКак и зачем использовать React HooksУправление состоянием в React через ContextКак предотвратить лишние ре-рендеры в React: полное руководствоuseMemo vs useCallback: подробное руководство по мемоизации в ReactПравила хуков — правила использованияuseEffect vs useLayoutEffect: в чём разница и какой хук выбрать?Кастомные хуки в React — создание собственных хуковuseState продвинутое использование в React
Transition API — плавные обновления интерфейса в ReactReact Suspense — приостановка рендераStrictMode в React — как находить ошибки на этапе разработкиСерверные компоненты React (RSC) — подробный разбор и практикаКак работает рендеринг в ReactЧто такое props в React и как их правильно использоватьКак работает JSX связка React и HTMLЧто такое React.js и как его использоватьКак использовать элементы в ReactКак использовать React DOM в проектеЧто такое компоненты в React и как их применятьРабота с children в ReactПорталы в React: рендер компонентов вне иерархии DOMFragment в React: группировка элементов без лишних узлов DOMCSS Modules в ReactConcurrent Mode — конкурентный режим в React
Открыть базу знаний

Лучшие курсы по теме

изображение курса

React и Redux Toolkit

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий