Разбираем работу пропсов
Вот и подошли мы к практической работе с пропсами! Пропсы (или props, сокращение от "properties") — это способ передачи данных в React-компоненты. Если представить компонент как функцию, то пропсы — это его "аргументы". Если бы компонент был автомобилем, то пропсы — это инструкция, которой вы объясняете ему, куда ехать, что везти и на какой скорости.
Пропсы позволяют компоненты делать гибкими и повторно используемыми, а это и есть одна из главных целей React.
Давайте рассмотрим ситуацию. У нас есть компонент Welcome, который выводит приветственное сообщение. Мы хотим передать в этот компонент имя пользователя, чтобы он приветствовал нас по имени. Вот пример:
// Пример передачи пропсов
type WelcomeProps = {
name: string; // Определяем, что проп `name` должен быть строкой
};
const Welcome: React.FC<WelcomeProps> = ({ name }) => {
return <h1>Привет, {name}!</h1>;
};
// Использование компонента с пропсами
const App = () => {
return <Welcome name="Иван" />;
};
Что тут происходит?
- Мы создали интерфейс
WelcomePropsдля типизации пропсов. - Компонент
Welcomeпринимает пропnameи рендерит его. - Когда мы используем
Welcomeвнутри компонентаApp, мы передаемname="Иван"как проп.
Почему пропсы важны?
Повторное использование компонентов
Представьте, что вы пишете таблицу, где каждая строка — это компонент. Вместо того чтобы писать код для каждой строки отдельно, вы просто создаете универсальный компонент строки, которому через пропсы передаете данные для рендера.
Гибкость
С помощью пропсов можно передавать не только текст или числа, но и сложные объекты, массивы, функции (да-да, функции тоже можно передавать, не удивляйтесь!).
Динамическое изменение данных через пропсы
Пропсы — это отличный способ динамически изменять данные компонентов. Например, мы можем создать компонент уведомления:
type NotificationProps = {
message: string;
type: "success" | "error";
};
const Notification: React.FC<NotificationProps> = ({ message, type }) => {
const styles = {
success: { color: "green" },
error: { color: "red" },
};
return <p style={styles[type]}>{message}</p>;
};
// Использование компонента
const App = () => {
return (
<>
<Notification message="Операция выполнена успешно!" type="success" />
<Notification message="Ошибка при выполнении операции!" type="error" />
</>
);
};
В этом примере пропсы message и type задают текст и стиль уведомления.
Композиция компонентов с пропсами
Пропсы позволяют "встраивать" компоненты друг в друга. Например:
// Компонент кнопки
type ButtonProps = {
onClick: () => void;
label: string;
};
const Button: React.FC<ButtonProps> = ({ onClick, label }) => {
return <button onClick={onClick}>{label}</button>;
};
// Компонент карточки
type CardProps = {
title: string;
onButtonClick: () => void;
};
const Card: React.FC<CardProps> = ({ title, onButtonClick }) => {
return (
<div>
<h2>{title}</h2>
<Button onClick={onButtonClick} label="Нажми меня" />
</div>
);
};
// Использование компонентов
const App = () => {
const handleClick = () => {
alert("Кнопка нажата!");
};
return <Card title="Заголовок карточки" onButtonClick={handleClick} />;
};
Здесь компонент Card использует компонент Button и передает ему пропсы. Таким образом, мы можем строить из маленьких блоков сложные интерфейсы.
Обработка необязательных пропсов
В жизни не всегда всё обязательно. Так и с пропсами. Иногда компонент может работать без некоторых из них. Для этого можно использовать ? в интерфейсе:
type WelcomeProps = {
name?: string;
};
const Welcome: React.FC<WelcomeProps> = ({ name }) => {
return <h1>Привет, {name ?? "Гость"}!</h1>;
};
// Использование компонента
const App = () => {
return (
<>
<Welcome name="Иван" />
<Welcome />
</>
);
};
Здесь проп name является необязательным. Если он не передан, компонент рендерит текст "Гость".
Пропсы — это однонаправленный поток данных
React следует принципу однонаправленного потока данных (unidirectional data flow). Это значит, что данные передаются из родительского компонента в дочерний, но не наоборот. Попытка изменить проп внутри дочернего компонента приведёт к ошибке.
Как это выглядит?
const Parent = () => {
const [name, setName] = useState("Иван");
return <Child name={name} />;
};
const Child: React.FC<{ name: string }> = ({ name }) => {
return <h1>Привет, {name}!</h1>;
};
Данные name определяются в родительском компоненте Parent и передаются дочернему компоненту Child. Если вы хотите, чтобы дочерний компонент мог как-то влиять на данные, передавайте функцию обратного вызова (callback) в пропсах.
Передача функций через пропсы
Вы можете передавать не только данные, но и функции:
type CounterProps = {
onIncrement: () => void;
onDecrement: () => void;
};
const Counter: React.FC<CounterProps> = ({ onIncrement, onDecrement }) => {
return (
<div>
<button onClick={onDecrement}>-</button>
<button onClick={onIncrement}>+</button>
</div>
);
};
const App = () => {
const handleIncrement = () => {
console.log("Увеличить");
};
const handleDecrement = () => {
console.log("Уменьшить");
};
return <Counter onIncrement={handleIncrement} onDecrement={handleDecrement} />;
};
Типичные ошибки и подводные камни
Не забывайте о типизации! Пропсы без типизации — это открытая дверь для ошибок. Убедитесь, что вы описываете интерфейсы для всех данных, которые передаете.
Пропсы неизменяемы (immutable). Если вы хотите изменить данные, переданные через пропсы, измените их в родительском компоненте и передайте обновленные данные.
Не передавайте слишком много пропсов. Если компонент принимает более 5–7 пропсов, это может говорить о плохой архитектуре. В таких случаях стоит использовать композицию или подумать о контексте.
Применение пропсов в реальной жизни
Пропсы используются в каждом React-приложении. Они позволяют создавать гибкие компоненты, которые вы можете повторно использовать в разных частях приложения. На собеседованиях часто просят написать компонент с пропсами, чтобы проверить, как вы работаете с потоками данных.
Не важно, создаете ли вы форму, таблицу или карточку продукта в интернет-магазине — пропсы — это ваши друзья.
Теперь, когда вы знаете, как работать с пропсами, вы готовы перейти к следующему важному шагу — типизации пропсов, чтобы сделать ваш код ещё более надёжным. 🎉
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ