Передача параметров¶
Компоненты React используют props для взаимодействия друг с другом. Каждый родительский компонент может передавать некоторую информацию своим дочерним компонентам, передавая им параметры. Параметры могут напомнить вам атрибуты HTML, но через них можно передавать любые значения JavaScript, включая объекты, массивы и функции.
Вы узнаете
- Как передать параметры компоненту
- Как читать параметры из компонента
- Как указать значения по умолчанию для параметров
- Как передать некоторый JSX в компонент
- Как параметры изменяются со временем
Известные параметры¶
Параметры - это информация, которую вы передаете в тег JSX. Например, className
, src
, alt
, width
и height
- вот некоторые из параметров, которые вы можете передать тегу <img>
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Параметры, которые вы можете передать тегу <img>
, предопределены (ReactDOM соответствует стандарту HTML). Но вы можете передавать любые параметры своим компонентам, таким как <Avatar>
, чтобы настроить их. Вот как!
Передача параметров компоненту¶
В этом коде компонент Profile
не передает никаких параметров своему дочернему компоненту Avatar
:
1 2 3 |
|
Вы можете передать Avatar
некоторые параметры в два этапа.
Шаг 1: Передайте параметры дочернему компоненту¶
Сначала передайте Avatar
некоторые параметры. Например, передадим два параметра: person
(объект) и size
(число):
1 2 3 4 5 6 7 8 9 10 11 |
|
Если двойные фигурные скобки после person=
вас смущают, вспомните они просто объект внутри JSX-скобок.
Теперь вы можете прочитать эти параметры внутри компонента Avatar
.
Шаг 2: Чтение параметров внутри дочернего компонента¶
Вы можете прочитать эти параметры, перечислив их имена person, size
, разделенные запятыми внутри ({
и })
непосредственно после функции Avatar
. Это позволит вам использовать их внутри кода Avatar
, как вы бы сделали это с переменной.
1 2 3 |
|
Добавьте в Avatar
логику, которая использует параметры person
и Size
для рендеринга, и все готово.
Теперь вы можете настроить Avatar
для рендеринга различными способами с различными параметрами. Попробуйте настроить значения!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
1 2 3 4 5 6 7 8 |
|
Параметры позволяют вам думать о родительских и дочерних компонентах независимо друг от друга. Например, вы можете изменить параметры person
или Size
внутри Profile
без необходимости думать о том, как Avatar
использует их. Аналогично, вы можете изменить, как Avatar
использует эти параметры, не заглядывая в Profile
.
Вы можете думать о параметрах как о "ручках", которые можно регулировать. Они выполняют ту же роль, что и аргументы для функций - фактически, параметр является единственным аргументом вашего компонента! Функции компонентов React принимают единственный аргумент - объект props
:
1 2 3 4 5 |
|
Обычно вам не нужен весь объект props
, поэтому вы деструктурируете его на отдельные параметры.
Внимание
Не пропустите пару символов {
и }
внутри (
и )
при объявлении параметров:
1 2 3 |
|
Этот синтаксис называется "деструктуризация" и эквивалентен чтению свойств из параметра функции:
1 2 3 4 5 |
|
Указание значения по умолчанию для параметра¶
Если вы хотите задать значение по умолчанию для параметра, когда значение не указано, вы можете сделать это с помощью деструктуризации, поместив =
и значение по умолчанию сразу после параметра:
1 2 3 |
|
Теперь, если <Avatar person={...} />
отображается без свойства size
, то size
будет установлен в 100
.
Значение по умолчанию используется только в том случае, если параметр size
отсутствует или если вы передали size={undefined}
. Но если вы передадите size={null}
или size={0}
, значение по умолчанию не будет использоваться.
Пересылка параметров с синтаксисом JSX spread¶
Иногда передача параметров становится очень повторяющейся:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Нет ничего плохого в повторяющемся коде - он может быть более разборчивым. Но иногда вам может быть важна краткость. Некоторые компоненты передают все свои параметры своим дочерним компонентам, например, как этот Profile
делает это с Avatar
. Поскольку они не используют параметры напрямую, имеет смысл использовать более лаконичный spread-синтаксис:
1 2 3 4 5 6 7 |
|
Это пересылает все параметры Profile
в Avatar
без перечисления имен каждого из них.
Используйте синтаксис распространения сдержанно. Если вы используете его в каждом втором компоненте, что-то не так. Часто это указывает на то, что вам следует разделить ваши компоненты и передавать дочерние компоненты как JSX. Подробнее об этом далее!
Передача JSX в качестве дочерних компонентов¶
Часто встречается вложение встроенных тегов браузера:
1 2 3 |
|
Иногда вы захотите вложить свои собственные компоненты таким же образом:
1 2 3 |
|
Когда вы вложите содержимое в JSX-тег, родительский компонент получит это содержимое в свойстве children
. Например, компонент Card
ниже получит параметр children
, установленный в <Avatar />
, и отобразит его в обертке div
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
1 2 3 4 5 6 7 8 |
|
Попробуйте заменить <Avatar>
внутри <Card>
каким-нибудь текстом, чтобы увидеть, как компонент Card
может обернуть любое вложенное содержимое. Ему не нужно "знать", что отображается внутри него. Вы увидите этот гибкий шаблон во многих местах.
Вы можете думать о компоненте с параметром children
как о компоненте с "дырой", которая может быть "заполнена" его родительскими компонентами с помощью произвольного JSX. Вы часто будете использовать параметр children
для визуальных оберток: панелей, сеток и т. д.
Как параметры меняются со временем¶
Компонент Clock
ниже получает два параметра от своего родительского компонента: color
и time
. (Код родительского компонента опущен, поскольку он использует state, в который мы пока не будем углубляться).
Попробуйте изменить цвет в поле выбора ниже:
1 2 3 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
|
Этот пример иллюстрирует, что компонент может получать различные параметры с течением времени. параметры не всегда статичны! Здесь параметр time
меняется каждую секунду, а параметр color
меняется, когда вы выбираете другой цвет. параметры отражают данные компонента в любой момент времени, а не только в начале.
Однако параметры являются иммутабельными- термин из информатики, означающий "неизменный". Когда компоненту нужно изменить свой параметр (например, в ответ на взаимодействие с пользователем или новые данные), он должен "попросить" свой родительский компонент передать ему другой параметр - новый объект! Его старые параметры будут отброшены, и в конечном итоге движок JavaScript вернет память, занятую ими.
Не пытайтесь "менять параметры". Когда вам нужно отреагировать на ввод пользователя (например, изменить выбранный цвет), вам нужно будет "установить состояние", о котором вы можете узнать в Состояние: Память компонента.
Итоги
- Чтобы передать параметры, добавьте их в JSX, точно так же, как это делается с атрибутами HTML.
- Чтобы прочитать параметр, используйте синтаксис деструктуризации
function Avatar({ person, size })
. - Вы можете указать значение по умолчанию, например
size = 100
, которое используется для отсутствующих инеопределенных
параметров. - Вы можете переслать все параметры с помощью
<Avatar {...props} />
Синтаксис распространения JSX, но не злоупотребляйте им! - Вложенные JSX типа
<Card><Avatar /></Card>
будут отображаться какдочерние
параметры компонентаCard
. - параметры - это снимки времени, доступные только для чтения: каждый рендер получает новую версию параметра.
- Вы не можете изменять параметры. Когда вам понадобится интерактивность, вам нужно будет установить состояние.
Задачи¶
1. Извлечение компонента¶
Этот компонент Gallery
содержит очень похожую разметку для двух профилей. Извлеките из него компонент Profile
, чтобы уменьшить дублирование. Вам нужно будет выбрать, какие параметры передать ему.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
|
1 2 3 |
|
Показать подсказку
Начните с извлечения разметки для одного из ученых. Затем найдите части, которые не соответствуют ему во втором примере, и сделайте их настраиваемыми с помощью параметров.
Показать решение
В этом решении компонент Profile
принимает несколько параметров: imageId
(строка), name
(строка), profession
(строка), awards
(массив строк), discovery
(строка) и imageSize
(число).
Обратите внимание, что параметр imageSize
имеет значение по умолчанию, поэтому мы не передаем его компоненту.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
|
1 2 3 |
|
Обратите внимание, что вам не нужен отдельный параметр awardCount
, если awards
- это массив. Тогда вы можете использовать awards.length
для подсчета количества наград. Помните, что параметр может принимать любые значения, в том числе и массивы тоже!
Другое решение, более похожее на предыдущие примеры на этой странице, заключается в том, чтобы сгруппировать всю информацию о человеке в одном объекте и передать этот объект как один параметр:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
|
1 2 3 4 5 6 7 8 |
|
Хотя синтаксис выглядит несколько иначе, поскольку вы описываете свойства объекта JavaScript, а не коллекцию атрибутов JSX, эти примеры в основном эквивалентны, и вы можете выбрать любой подход.
2. Настройте размер изображения на основе параметров¶
В этом примере Avatar
получает числовой параметр size
, который определяет ширину и высоту <img>
. В данном примере параметр size
установлен на 40
. Однако если вы откроете изображение в новой вкладке, вы заметите, что само изображение больше (160
пикселей). Реальный размер изображения определяется тем, какой размер миниатюры вы запрашиваете.
Измените компонент Avatar
, чтобы он запрашивал наиболее близкий размер изображения на основе параметра size
. В частности, если size
меньше 90
, передавайте 's'
("small"), а не 'b'
("big") в функцию getImageUrl
. Проверьте, что ваши изменения работают, отобразив аватары с разными значениями параметра size
и открыв изображения в новой вкладке.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
1 2 3 4 5 6 7 8 |
|
Показать решение
Вот как вы можете поступить:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
1 2 3 4 5 6 7 8 |
|
Вы также можете показать более четкое изображение для экранов с высоким DPI, принимая во внимание window.devicePixelRatio
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
|
1 2 3 4 5 6 7 8 |
|
Параметры позволяют инкапсулировать подобную логику внутри компонента Avatar
(и изменить ее позже, если потребуется), чтобы каждый мог использовать компонент <Avatar>
, не задумываясь о том, как запрашиваются и изменяются размеры изображений.
3. Передача JSX в children
параметр¶
Извлеките компонент Card
из приведенной ниже разметки и используйте параметр children
для передачи ему различных JSX:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Показать подсказку
Любой JSX, который вы поместите внутрь тега компонента, будет передан в качестве параметра children
этому компоненту.
Показать решение
Вот как вы можете использовать компонент Card
в обоих местах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
Вы также можете сделать title
отдельным параметром, если хотите, чтобы каждая Card
всегда имела заголовок:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Источник — https://react.dev/learn/passing-props-to-a-component