Главная / Статьи

React Props для начинающих: преобразование статических компонентов в шаблоны

Узнайте, как React-пропсы передают данные от родительских к дочерним компонентам, как работает объект пропсов, какие типы значений можно передавать и почему однонаправленный поток данных способствует эффективной работе.

Издатель: REACTAPP.TOP7 мин чтения1586 слов

Источники: 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-компонентов.

Основные выводы

  • Свойства — это значения, которые родительский компонент передает дочернему при его отрисовке.
  • Данные передаются только в одном направлении, от родителя к дочернему, причем дочерние компоненты рассматривают свойства как только для чтения.
  • React собирает все атрибуты тега компонента в один объект props, который передается как первый аргумент функции.
  • Для строк могут использоваться кавычки; числа, логические значения, переменные и выражения помещаются в круглые скобки.
  • Один компонент с разными атрибутами заменяет множество почти идентичных компонентов.
  • Следующими логичными шагами являются разбор атрибутов с помощью деструктуризации, передача объектов, массивов и функций-обратных вызовов, указание значений по умолчанию и использование атрибута children.