Props и их типизация

В экосистеме React props (сокращение от properties) представляют собой механизм передачи данных от родительского компонента к дочернему. Они позволяют компонента работать с динамическими значениями и конфигурировать его поведение без необходимости изменения внутреннего состояния.


Передача props

Props передаются в компонент через атрибуты в JSX:

function Button({ label, onClick }) {
    return <button onCl ick={onClick}>{label}</button>;
}

function App() {
    return <Button label="Нажми меня" onCl ick={() => alert('Clicked!')} />;
}

Ключевые моменты:

  • Props только для чтения. Изменять их внутри компонента нельзя.
  • Любой компонент может принимать неограниченное количество props.
  • Props могут быть примитивными значениями, объектами, функциями или даже JSX-элементами.

Деструктуризация props

Часто props деструктурируют сразу в параметрах функции:

function Card({ title, description }) {
    return (
        <div>
            <h2>{title}</h2>
            <p>{description}</p>
        </div>
    );
}

Деструктуризация упрощает доступ к отдельным значениям и делает код более читаемым.


Значения по умолчанию

Для props можно задавать значения по умолчанию через объект defaultProps или через параметр функции:

function Badge({ text = "Новый" }) {
    return <span>{text}</span>;
}

// или для классового компонента
Badge.defaultProps = {
    text: "Новый"
};

Default props обеспечивают корректное поведение компонента даже при отсутствии соответствующего атрибута.


Типизация props с PropTypes

Для проверки типов props используется пакет prop-types. Он позволяет явно указать, какого типа должны быть props и обязательны ли они.

import PropTypes from 'prop-types';

function Profile({ name, age }) {
    return <div>{name}, {age} лет</div>;
}

Profile.propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number
};

Особенности:

  • PropTypes.string — строка
  • PropTypes.number — число
  • PropTypes.bool — булев тип
  • PropTypes.func — функция
  • PropTypes.array — массив
  • PropTypes.object — объект

Можно использовать сложные типы, например массив объектов:

Profile.propTypes = {
    friends: PropTypes.arrayOf(
        PropTypes.shape({
            id: PropTypes.number.isRequired,
            name: PropTypes.string.isRequired
        })
    )
};

Типизация props с TypeScript

TypeScript обеспечивает статическую проверку типов на этапе компиляции, делая код безопаснее и предотвращая ошибки в рантайме.

interface ButtonProps {
    label: string;
    onClick: () => void;
}

function Button({ label, onClick }: ButtonProps) {
    return <button onCl ick={onClick}>{label}</button>;
}

Преимущества TypeScript:

  • Явная типизация всех props.
  • Подсказки IDE и автодополнение.
  • Снижение числа runtime ошибок.
  • Возможность типизировать сложные структуры: массивы, объекты, функции с параметрами.

Типизация сложных props:

interface User {
    id: number;
    name: string;
}

interface UserListProps {
    users: User[];
    onSelect: (user: User) => void;
}

function UserList({ users, onSelect }: UserListProps) {
    return (
        <ul>
            {users.map(user => (
                <li key={user.id} onCl ick={() => onSelect(user)}>
                    {user.name}
                </li>
            ))}
        </ul>
    );
}

Передача функций через props

Props часто используются для передачи функций из родителя в дочерний компонент. Это позволяет дочернему компоненту взаимодействовать с внешним состоянием.

function Counter({ onIncrement }) {
    return <button onCl ick={onIncrement}>Увеличить</button>;
}

function App() {
    const [count, setCount] = React.useState(0);

    return (
        <div>
            <p>Счёт: {count}</p>
            <Counter onIncrem ent={() => setCount(count + 1)} />
        </div>
    );
}

Особенности:

  • Функции в props могут быть стрелочными или обычными.
  • Функции сохраняют ссылку на родительский контекст.
  • Часто используется для поднятия состояния (lifting state up).

Рендер-пропы

Особый паттерн передачи данных через props — render props, когда дочерний компонент получает функцию для рендера UI:

function List({ items, render }) {
    return <ul>{items.map(render)}</ul>;
}

<List
    items={[1, 2, 3]}
    render={item => <li key={item}>{item}</li>}
/>

Преимущества render props:

  • Полная кастомизация рендера дочернего компонента.
  • Возможность разделять логику и отображение.
  • Упрощение переиспользования компонентов.

Children как особый тип props

children — это стандартный prop, который содержит вложенный JSX:

function Container({ children }) {
    return <div className="container">{children}</div>;
}

<Container>
    <p>Вложенный контент</p>
</Container>

Особенности:

  • children может быть элементом, массивом элементов или строкой.
  • Позволяет создавать высоко переиспользуемые обертки.

Вывод

Props — ключевой механизм передачи данных в React. Их правильная типизация с помощью PropTypes или TypeScript обеспечивает безопасное взаимодействие между компонентами, улучшает читаемость кода и предотвращает ошибки. Использование функций, children и render-пропов расширяет возможности компонентов, делая их гибкими и переиспользуемыми.