Пропсы (props, от properties) представляют собой способ передачи данных от родительского компонента к дочернему. Они являются неизменяемыми внутри компонента: компонент получает пропсы и использует их для рендеринга интерфейса или передачи дальше. В отличие от состояния (state), которое может меняться внутри компонента, пропсы служат для конфигурации и передачи информации извне.
Пример базового компонента с пропсами:
import { h } from 'preact';
function Button({ label, onClick }) {
return (
<button onCl ick={onClick}>
{label}
</button>
);
}
В этом примере label и onClick — это
пропсы. Они определяются в момент использования компонента:
<Button label="Нажми меня" onCl ick={() => alert('Клик!')} />
Preact поддерживает деструктуризацию пропсов прямо в сигнатуре функции компонента, что делает код более читаемым:
function Card({ title, content, footer }) {
return (
<div className="card">
<h2>{title}</h2>
<p>{content}</p>
<div className="card-footer">{footer}</div>
</div>
);
}
Такой подход упрощает доступ к отдельным пропсам без необходимости
писать props.title, props.content и т.д.
Чтобы компонент корректно работал даже при отсутствии некоторых пропсов, Preact позволяет задавать значения по умолчанию. Для функциональных компонентов можно использовать стандартные возможности Jav * aScript:
function Badge({ text = 'Новый', color = 'blue' }) {
return <span style={{ backgroundColor: color }}>{text}</span>;
}
Если компонент вызывается без пропсов:
<Badge />
Он всё равно отобразит «Новый» с синим фоном.
Хотя Preact не имеет встроенной строгой типизации, TypeScript позволяет описывать интерфейсы пропсов, что обеспечивает безопасность и автодополнение:
interface UserCardProps {
name: string;
age?: number;
}
function UserCard({ name, age }: UserCardProps) {
return (
<div>
<h3>{name}</h3>
{age && <p>Возраст: {age}</p>}
</div>
);
}
Символ ? в интерфейсе означает, что пропс
age необязательный. Такой подход особенно полезен при
работе с крупными приложениями, где компоненты имеют большое количество
параметров.
Пропсы позволяют передавать не только данные, но и функции. Это основной способ обработки событий в дочерних компонентах:
function Counter({ onIncrement }) {
return (
<button onCl ick={onIncrement}>
Увеличить
</button>
);
}
function App() {
const handleIncrement = () => console.log('Счётчик увеличен');
return <Counter onIncrem ent={handleIncrement} />;
}
Функции в пропсах дают возможность управлять состоянием родительского компонента из дочернего, сохраняя архитектуру приложения чистой и предсказуемой.
В Preact компоненты, вызываемые через JSX, могут принимать любые значения как пропсы: строки, числа, массивы, объекты и даже JSX-элементы:
function List({ items }) {
return (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
}
<List items={[{ id: 1, name: 'Элемент 1' }, { id: 2, name: 'Элемент 2' }]} />
Важно использовать уникальные ключи (key) при рендеринге
списков, чтобы Preact корректно отслеживал изменения и оптимизировал
обновления DOM.
Для передачи большого количества пропсов удобно использовать spread-оператор:
const buttonProps = { label: 'Сохранить', onClick: () => console.log('Сохранено') };
<Button {...buttonProps} />
Это особенно полезно при работе с компонентами, которые требуют множества параметров, и позволяет избежать явного перечисления каждого пропса.
Хотя пропсы сами по себе неизменяемы, переданные объекты и массивы могут быть модифицированы внутри компонента, что может привести к непредсказуемым результатам. Рекомендуется всегда использовать копии данных или методы, возвращающие новые объекты:
function Items({ list }) {
const newList = [...list, { id: 3, name: 'Новый элемент' }];
return newList.map(item => <div key={item.id}>{item.name}</div>);
}
Это предотвращает нежелательные побочные эффекты при работе с пропсами.
Часто компоненты используют одновременно пропсы и локальное состояние. Пропсы задают начальные значения или конфигурацию, а состояние управляет динамическими изменениями:
function Toggle({ initial = false }) {
const [isOn, setIsOn] = useState(initial);
return (
<button onCl ick={() => setIsOn(!isOn)}>
{isOn ? 'Вкл' : 'Выкл'}
</button>
);
}
initial — это пропс, задающий стартовое состояние.
Дальнейшие изменения происходят через useState, не
затрагивая исходный пропс.
Пропсы позволяют передавать компоненты как значения, что упрощает создание универсальных и переиспользуемых компонентов:
function Modal({ header, body, footer }) {
return (
<div className="modal">
<div className="modal-header">{header}</div>
<div className="modal-body">{body}</div>
<div className="modal-footer">{footer}</div>
</div>
);
}
<Modal
header={<h2>Заголовок</h2>}
body={<p>Содержимое модального окна</p>}
footer={<button>Закрыть</button>}
/>
Такой подход делает интерфейсы гибкими и позволяет легко менять содержимое модальных окон, карточек и других компонентов без изменения их внутренней логики.