TL;DR
Разбираем паттерны именования пропсов через игровой формат “угадай правильное название”. Практические примеры на TypeScript, антипаттерны и как избежать prop drilling без Context API. Для тех, кто хочет прокачать свою компонентную интуицию.
Введение: Почему нейминг пропсов — это боль
В React-экосистеме до сих пор нет конвенции по именованию пропсов уровня AIRBNB JS Style Guide. В результате мы получаем:
<Modal
onCloseRequest={() => {}}
handleSubmit={submit}
didOpen={true}
closeModalCallback={close}
/>
Типичный пример “пропсового ада”, где смешаны:
- Глагольные/субстантивные формы (
onCloseRequestvshandleSubmit) - Префиксная несогласованность (
closeModalCallbackвместоonClose) - Булевые антипаттерны (
didOpenвместоisOpen)
Основная часть: Играем в “Props или не Props”
Уровень 1: Базовые пропсы
Задача: Выберите корректный вариант:
// Вариант A
<Button
onClick={() => {}}
disabled={false}
/>
// Вариант B
<Button
handleClick={() => {}}
isDisabled={false}
/>
Ответ: Оба варианта допустимы, но Option A предпочтительнее для базовых HTML-атрибутов. Правило:
“Когда пропс соответствует native DOM prop — сохраняем оригинальное имя”
Уровень 2: Колбэки
Сложный кейс с обработчиками:
// Вариант A
<Form
beforeSubmit={() => {}}
afterSubmitSuccess={() => {}}
/>
// Вариант B
<Form
onSubmitStart={() => {}}
onSubmitSuccess={() => {}}
/>
Анализ:
- Вариант A нарушает принцип инверсии контроля — непонятно, кто вызывает
beforeSubmit - Вариант B использует стандартную префиксацию
on*для колбэков
Уровень 3: Булевые флаги
Типичная ошибка junior-ов:
// Антипаттерн
<Dropdown
isOpen={true}
isDisabled={false}
shouldCloseOnClick={true}
/>
// Паттерн
<Dropdown
open={true}
disabled={false}
closeOnClick={true}
/>
Правило:
“Избегайте избыточных префиксов
is/shouldдля булевых пропсов, кроме случаев, когда это улучшает читаемость”
Практика: Рефакторинг реального компонента
До:
<UserCard
userData={user}
handleAvatarClick={() => {}}
isSubscriptionActive={false}
makeUserAdminHandler={() => {}}
/>
После:
<UserCard
user={user}
onAvatarClick={() => {}}
subscriptionActive={false}
onMakeAdmin={() => {}}
/>
Ключевые изменения:
- Убрали суффикс
Data— тип ясен из контекста - Привели колбэки к единому формату
on* - Упростили булевые пропсы
Продвинутые техники
Типизация пропсов через TS Utility Types
type Props = {
size: 'sm' | 'md' | 'lg';
variant?: 'primary' | 'secondary';
} & React.ComponentPropsWithoutRef<'button'>;
const Button = ({ size, variant, ...rest }: Props) => (
<button className={`btn-${size} ${variant}`} {...rest} />
);
Компоненты-фабрики
const createInput = (type: 'text' | 'email') => {
const Input = (props: Omit<ComponentProps<'input'>, 'type'>) => (
<input type={type} {...props} />
);
return Input;
};
const EmailInput = createInput('email');
Заключение
Игра “Props или не Props” — это не просто развлечение, а способ выработать профессиональную интуицию. Основные правила:
- Колбэки — только с
on*префиксом - Булевы пропсы — без избыточных
is/should - Сохраняем native DOM prop names там, где это уместно
Для дальнейшего погружения рекомендую:
Источник: https://cant-maintain.saschb2b.com/