Props: передача данных
Props (properties) — механизм передачи данных от родительского компонента к дочернему; props иммутабельны внутри компонента-получателя.
Зачем нужно
Props — основной способ связи между компонентами в React. Понимание их работы необходимо с первых дней: через props передаются данные, обработчики событий, дочерние компоненты и конфигурация. Правильная типизация props через TypeScript позволяет поймать ошибки до запуска и делает API компонента самодокументируемым.
Где используется
- Передача данных с уровня страницы в компоненты (список товаров → карточка товара)
- Конфигурация переиспользуемых UI-компонентов (Button variant, Input placeholder)
- Передача колбэков для обратной связи от дочернего к родительскому
- Компоновка через
children
Основы Props
// Компонент принимает props как аргумент
function UserCard({ name, email, role, onEdit }) {
return (
<div className="user-card">
<h3>{name}</h3>
<p>{email}</p>
<span className={`badge badge--${role}`}>{role}</span>
<button onClick={ => onEdit({ name, email })}>
Редактировать
</button>
</div>
);
}
// Использование — передача props как атрибутов
function UserList({ users }) {
return (
<ul>
{users.map(user => (
<UserCard
key={user.id}
name={user.name}
email={user.email}
role={user.role}
onEdit={(data) => console.log('Редактируем:', data)}
/>
))}
</ul>
);
}
TypeScript + props
// Типизация через interface
interface ButtonProps {
children: React.ReactNode;
variant?: 'primary' | 'secondary' | 'danger';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
}
function Button({
children,
variant = 'primary', // значение по умолчанию
size = 'md',
disabled = false,
onClick,
}: ButtonProps) {
return (
<button
className={`btn btn--${variant} btn--${size}`}
disabled={disabled}
onClick={onClick}
>
{children}
</button>
);
}
Паттерн: children и render props
// children — специальный проп для вложенного содержимого
function Card({ children, title }) {
return (
<div className="card">
{title && <h2 className="card__title">{title}</h2>}
<div className="card__body">{children}</div>
</div>
);
}
// Использование с children
<Card title="Профиль пользователя">
<UserInfo user={currentUser} />
<UserStats stats={userStats} />
</Card>
// Spread props — передача остальных пропсов
function Input({ label, error, ...inputProps }) {
return (
<label>
{label}
<input {...inputProps} /> {/* value, onChange, type и т.д. */}
{error && <span className="error">{error}</span>}
</label>
);
}
Частые ошибки
- Мутация props —
props.items.push(newItem)внутри компонента нарушает однонаправленный поток данных; для изменений используйте state. - Передача всего объекта вместо нужных полей —
<Card user={user} />вместо<Card name={user.name} email={user.email} />нарушает инкапсуляцию и усложняет переиспользование. - Пропуск key при рендере списков —
keyнужен при рендере массива компонентов, но это отдельный механизм, не обычный prop. - Слишком много props — если компонент принимает 10+ пропсов, это сигнал о нарушении принципа единственной ответственности.
Связанные темы
- _MOC SPA
- Компонент -- что это такое
- Props Drilling -- проблема
- State -- внутреннее состояние
- Контролируемые и неконтролируемые компоненты