React Props для начинающих: преобразование статических компонентов в шаблоны
Узнайте, как React-пропсы передают данные от родительских к дочерним компонентам, как работает объект пропсов, какие типы значений можно передавать и почему однонаправленный поток данных способствует эффективной работе.
Источники: Part 5A — React Props Explained: Pass Data Between Components Like a Pro
Разделение интерфейса React на компоненты — это лишь половина процесса повторного использования. Компонент, который всегда отображает один и тот же текст, является просто единицей для копирования и вставки, а не строительным блоком. Параметры (props) — это механизм, позволяющий одному и тому же компоненту отображать разный контент при каждом использовании. В этом руководстве объясняется, что такое параметры, как передаются данные от родителя к дочернему компоненту, как читать параметры внутри компонента и какие типы значений можно передавать, чтобы превратить жестко закодированные компоненты в повторно используемые шаблоны.
Когда компонент может отображать только одну вещь
Как только вы научитесь создавать компоненты, типичная структура приложения будет выглядеть примерно так: корневой компонент App отображает несколько разделов:
App
│
├── Navbar
├── Hero
├── Features
├── Footer
Теперь представьте карточку товара в интернет-магазине. Она отображает название, цену, оценку и кнопку покупки:
-------------------------
📱 iPhone 16
₹79,999
⭐⭐⭐⭐⭐
Buy Now
-------------------------
Затем появляется требование: отобразить 500 продуктов. Текущая структура позволяет показать только один телефон по определенной цене, поэтому для ноутбуков, наушников и часов потребуется почти идентичный компонент, что сводит на нет смысл использования отдельных компонентов. Необходимо сохранять фиксированную структуру, при этом каждый раз подставляя разные данные. Именно для этого и существуют пропсы.
Что такое пропсы
«Пропсы» — это сокращение от «properties». Это значения, которые родительский компонент передает дочернему при его отрисовке. Компонент определяет структуру и стиль; пропсы предоставляют детали, делающие каждый экземпляр уникальным.
Поможет аналогия с кухней. Пиццерия не придумывает новый рецепт для каждого заказа. У нее есть один рецепт, а по каждому заказу она получает разные инструкции: дополнительный сыр, грибы, оливки, кукуруза. Рецепт — это компонент, а добавки — пропсы.
Другими словами, компонент выступает в роли шаблона, а пропсы заполняют его поля. Вместо того чтобы создавать отдельную карточку, которая всегда показывает одно и то же, как здесь:
Product Card
iPhone
вы создаёте одну универсальную карточку продукта и передаёте ей разные данные там, где она используется.
Родительские и дочерние компоненты, однонаправленный поток данных
Пропсы имеют смысл только в контексте отношений между компонентами. Каждое приложение React представляет собой дерево, в котором некоторые компоненты отрисовывают другие:
App
│
├── Navbar
├── Hero
├── ProductCard
└── Footer
Здесь App является родительским компонентом, а Navbar, Hero, ProductCard и Footer — его дочерними. Родительский компонент решает, какие дочерние компоненты отрисовать, и может также передавать каждому из них информацию. Эта информация и есть его пропсы.
React обеспечивает однонаправленный поток данных: пропсы передаются вниз, от родительского к дочернему компоненту.
App
│
│ title
│ price
│ rating
▼
ProductCard
Подкомпонент получает title, price и rating, но не может возвращать новые значения через свои пропсы. С точки зрения подкомпонента пропсы также являются только для чтения. Компонент никогда не должен изменять пропсы, которые он получает; если что-то нужно изменить со временем, это должно находиться в состоянии, которым обычно управляет родительский компонент. Когда подкомпоненту необходимо передать информацию вверх, например о нажатии, родительский компонент передаёт ему функцию в качестве пропса, и подкомпонент вызывает её. Поскольку данные передаются только в одном направлении, вы всегда можете отследить происхождение значения, двигаясь вверх по иерархии компонентов, что значительно упрощает поиск ошибок.
Ваш первый компонент с пропсами
Начните с компонента, который приветствует человека по имени. Он принимает параметр под названием props и читает значение props.name внутри своего JSX:
function Welcome(props) {
return (
<h1>Hello, {props.name}</h1>
);
}
export default Welcome;
Родительский компонент отрисовывает его и передаёт имя в качестве атрибута:
import Welcome from "./Welcome";
function App() {
return (
<>
<Welcome name="Ayush" />
</>
);
}
export default App;
Результат отрисовки:
Hello, Ayush
Что делает каждая часть синтаксиса
Передача пропсов похожа на добавление атрибута HTML в тег компонента:
<Welcome name="Ayush" />
Удобно рассматривать это как вызов функции с аргументами. С точки зрения принимающего компонента, он является функцией, первым параметром которой являются пропсы:
function Welcome(props)
React собирает все атрибуты, которые вы указали в теге, в один обычный объект и передаёт его в качестве этого параметра. Чтение значения — это обычный доступ к свойству:
props.name
Поскольку родительский компонент передал этот атрибут:
name="Ayush"
компонент отрисовывает:
Hello, Ayush
Имя props является лишь конвенцией. Во многих кодовых базах оно разбирается в списке параметров, как в примере function Welcome({ name }).
Передача нескольких параметров одновременно
В реальных компонентах обычно требуется более одного значения. Можно добавить столько атрибутов, сколько нужно. Обратите внимание: строки пишутся в кавычках, а числа и другие значения JavaScript — в фигурных скобках. В приведённом ниже фрагменте отсутствует пробел между именем компонента и первым атрибутом; правильно будет <Welcome name=...:
<Welcomename="Ayush"
company="OpenAI"
experience={6}
/>
Компонент читает каждый параметр по имени:
function Welcome(props) {
return (
<>
<h2>{props.name}</h2>
<p>{props.company}</p>
<p>{props.experience} Years</p>
</>
);
}
И отображает:
Ayush
OpenAI
6 Years
При изменении параметров тот же компонент отображает совершенно другую информацию.
Повторно используемая карточка товара
Возвращаемся к магазину. Теперь картка считывает своё название, цену и оценку из атрибутов, вместо того чтобы задавать их явно:
function ProductCard(props) {
return (
<div>
<h2>{props.title}</h2>
<p>₹ {props.price}</p>
<p>{props.rating}</p>
</div>
);
}
export default ProductCard;
Родительский компонент может отрисовать столько карток, сколько необходимо, причем у каждой будет собственные данные. Цена передаётся в виде числа в круглых скобках, а название и оценка — как строки:
<ProductCard
title="iPhone 16"
price={79999}
rating="⭐⭐⭐⭐⭐"
/>
<ProductCard
title="Samsung S25"
price={68999}
rating="⭐⭐⭐⭐"
/>
<ProductCard
title="MacBook Air"
price={99999}
rating="⭐⭐⭐⭐⭐"
/>
Один компонент, три разных продукта, без дублирования маркировки. Для 500 продуктов вы тоже не будете вручную писать 500 тегов: данные будут браться из массива, и картки будут отрисовываться с помощью products.map(...), причём поля каждого элемента будут передаваться как атрибуты, а каждой картке будет присвоен уникальный key.
Почему атрибуты позволяют повторное использование
Без атрибутов магазину потребуется отдельный компонент для каждого продукта:
ProductCard1
ProductCard2
ProductCard3
ProductCard4
ProductCard5
Это означает наличие множества файлов с практически идентичным кодом, при котором любые изменения дизайна приходится вносить повторно во всех местах. С использованием пропсов процесс выглядит так: один компонент получает различные данные:
ProductCard
↓
Different Product Data
↓
Multiple Cards
Один файл определяет структуру карточки; её экземпляры отличаются только данными. Это основной принцип, лежащий в основе крупных React-приложений и систем дизайна.
Представьте стандартную форму приложения: все заполняют одни и те же поля — имя, возраст и адрес — но с разными данными. Пустая форма — это компонент; введенные данные — пропсы.
Какие типы значений можно передавать
Пропсы не ограничиваются текстом. Можно передавать любые значения JavaScript. Для строк используются кавычки:
name="Ayush"
Числа заключаются в круглые скобки, так что React получает реальное число, а не строку “26”:
age={26}
Для логических значений также используются скобки:
isAdmin={true}
Можно передать значение переменной:
name={username}
Или результат любого выражения, которое оценивается до того, как его получит дочерний элемент:
price={500 + 200}
Массивы, объекты и функции могут передаваться таким же образом внутри скобок. Функции в качестве свойств служат способом для дочерних элементов уведомлять родительские элементы о событиях, а специальное свойство под названием children позволяет компоненту обернуть любой маркап, размещенный между его открывающими и закрывающими тегами.
Заглушенные значения против свойств
Сравните заголовок с заложенным значением:
<h2>iPhone 16</h2>
и заголовок, определяемый свойством:
<h2>{props.title}</h2>
Первый компонент может отображать только один продукт; второй — любое количество. Каждый раз, когда вы начинаете вводить конкретный контент в компонент, предназначенный для повторного использования, спросите себя, не лучше ли сделать этот контент свойством. Избегайте противоположного крайнего случая: превращение каждой мелочи в свойство затрудняет использование компонентов, поэтому выделяйте только то, что действительно меняется при разных использованиях.
Чтобы вспомнить, как структурируются сами компоненты, ознакомьтесь с основами React-компонентов.
Основные выводы
- Свойства — это значения, которые родительский компонент передает дочернему при его отрисовке.
- Данные передаются только в одном направлении, от родителя к дочернему, причем дочерние компоненты рассматривают свойства как только для чтения.
props, который передается как первый аргумент функции.children.