Способы передачи данных между компонентами в React
React имеет различные способы передачи данных между своими компонентами:Render props / props; Context; React-Redux / Redux.
В React есть несколько способов передачи данных между компонентами: Render props / props, Context, React-Redux / Redux.
В этой статье вы узнаете об этих способах подробно. В каждом из них вы научитесь добиваться двух вариантов взаимодействия:
- от родителя к наследнику;
- от наследника к родителю.
Render props / props
Один из самых простых способов передачи данных в компоненты — это props (свойства).
Что такое prop?
Как известно, разметка в компонентах рендерится так:
class C extends React.Component < render() < return ( C component ) > > class P extends React.Component < render() < return ( ) > >
Это отобразится как C component
C фактически отображается в P, так как P является его родительским компонентом. Кроме того, P может отобразить C следующим образом:
class P extends React.Component < render() < return ( ) > >
P добавляет дополнительные свойства в тег элемента C. Это очень похоже на в HTML, где id — это атрибут со значением “nnamdi”. Каждый элемент на самом деле является отдельным экземпляром класса HTMLElement .
Тег анализируется движком рендеринга в браузере, и для каждого тега создаются экземпляры класса HTMLElement . Все теги в HTML имеют соответствующий HTMLElement :
div -> HTMLDivElement anchor -> HTMLAnchorElement body -> HTMLBodyElement button -> HTMLButtonElement .
Каждый HTML*Element выше является подклассом HTMLElement . Эти HTML*Element имеют методы и свойства, которые можно использовать для манипулирования данными и рендеринга.
HTML*Element - appendChild - attributes - getAttribute - hasAttribute - innerHTML - innerText - setAttribute .
В случае выше будет создан HTMLDivElement :
const divElement = new HTMLDivElement() divElement.setAttribute("name", "nnamdi")
Имя атрибута будет установлено в объект props вот так:
props =
и передастся классу компонента C с помощью React.
class C extends React.Component < constructor(props) < >. >
Таким образом, компонент C может получить доступ к значению name в объекте props через props.name .
class C extends React.Component < constructor(props) < log(this.props.name) // nnamdi >. >
React основан на JSX, поэтому разметка в P будет скомпилирована в таком виде:
| | | | v React.createElement(C, < name:"nnamdi" >)
Первый параметр — это элемент для рендеринга, а второй содержит атрибуты элемента (в виде объектного литерала). CreateElement возвращает литерал, содержащий первый и второй параметры.
При рендеринге React проверяет, является ли этот литерал на самом деле элементом или же классом. Если это класс, React создаёт его экземпляр, используя ключевое слово new, затем передает этот экземпляр в объект props и вызывает метод render.
const objType = React.createElement(C, < name:"nnamdi" >) if(IS_ELEMENT(objType)) < //. >else < if(IS_CLASS(objType))< const klass = objType.component // klass теперь содержит класс C, класс С расширяет React.Component ` const props = objType.props // props содержит < name: "nnamdi" >, атрибуты переданы компоненту С в компоненте P `` const klzz = new klass(props) // здесь klass создаётся и ему передается props. klzz.componentWillMount() klzz.render() klzz.componentDidMount() //. > >
Приведённый выше код показывает, что фактически делает React для рендеринга компонента или элемента.
Примечание: фрагмент выше не полный, он нужен, чтобы продемонстрировать, как компоненты получают аргумент props.
Сначала проверяется, является ли objType элементом или классом. Затем IS_ELEMENT(…) проверяет список всех элементов HTML. Если objType соответствует одному из них, то возвращается флаг true: значит objType является элементом. Если IS_ELEMENT(…) возвращает false, то, objType должен быть компонентом класса, тогда он уничтожает props и экземпляр класса из objType . Затем он создаёт новый экземпляр класса, используя ключевое слово new и передавая его в props.
Таким образом P удаётся отправить данные в C.
Но как C теперь может отправлять данные обратно в родительский класс P? Это делается с помощью render props.
Что такое render props? Это концепция, посредством которой функция может быть передана дочерним компонентам в качестве свойства (props). Строка, объект, число или массив могут быть переданы через props дочерним компонентам. Это реализовано следующим образом:
> /> class C extends React.Component < constructor(props)< this.props.func() >render() < return ( ) > >
Здесь функция () => передаётся компоненту C через свойство func. Затем компонент C может ссылаться на неё через func в аргументе props. Это функция выводит render props в консоли.
Итак, теперь вы знаете, что такое render props (или свойства для рендеринга). Давайте посмотрим, как дочерние компоненты могут использовать их для связи с родительскими.
class P extends React.Component < constructor() < this.output = this.output.bind(this) >output() < log("With love from parent P land :)") >render() < return ( /> ) > > class C extends React.Component < constructor(props) <>render() < return ( C component ) > >
Что происходит в этом фрагменте? У компонента P метод вывода связан с его экземпляром. bind(this) говорит JS запустить функцию внутри области видимости класса, объекта или функции. Вывод здесь выполняется за пределами класса P, но он по-прежнему может ссылаться на все свойства и методы, определённые в P.
Таким образом, метод вывода передаётся в компонент класса C, чтобы получить аргумент props через свойство func.
К кнопке «Send To Parent» компонента C привязано событие onclick , необходимое для вызова метода вывода, с переданным в него аргументом props через func. Так что теперь this.props.func в C содержит метод вывода в классе P:
this.props.func === new P().output
Предположим, кнопка «Send To Parent» нажата. Вызывается this.props.func , ссылаясь на метод вывода в P, далее вызывается сам метод вывода. В консоли будет отображено следующее:
With love from parent P land :)
Теперь C успешно связался со своим родителем P. Можно изменить код, чтобы C отправлял данные в P.
class P extends React.Component < constructor() < this.output = this.output.bind(this) this.state = < count: 0 >> output(evt) < log("With love from parent P land :)") this.setState() > render() < return ( Count: /> ) > > class C extends React.Component < constructor(props) <>render() < return ( C component ) > >
В этом фрагменте кода в P добавляется состояние, которое содержит свойство count . В C при нажатии кнопки «Send To Parent» генерируется случайное число и передаётся в this.props.func . Метод вывода компонента P перехватывает значение из аргумента evt и обновляет состояние count полученным значением, вызывая this.setState(…) .
Как вы видите, значение P отправилось из его дочернего элемента C.
Свойство Parent можно изменить, передав функцию компоненту Child и вызвав эту функцию внутри компонента Child .
Props и render props — это одно и то же, но они имеют разные концепции. Render props в основном используется для разделения логики рендеринга между компонентами. Но в данном случае этот метод был использован для передачи данных от дочернего компонента к родительскому.
Context
Для большинства разработчиков передача props глубоко вложенным компонентам в дереве была бы утомительной. React предоставляет способ определять глобальные данные в одном месте и получать к ним доступ из любого места в приложении.
Context (контекст) как раз используется в React для обмена данными между глубоко вложенными компонентами.
const ColorContext = React.createContext("yellow") class App extends React.Component < render() < return ( ) > > class P extends React.Component < render() < return ( ) > > class C extends React.Component < render() < return ( ) > > class Sub-C extends React.Component < render() < > >
В этом фрагменте есть три компонента в дереве: App -> P -> C -> Sub-C . App отображает P, P отображает C, а C отображает Sub-C, который определён как context с именем ColorContext . P заключён в ColorContext.Provider , это обеспечивает доступ к данным, определённым в ColorContext , всем дочерним компонентам P.
Дочерние компоненты могут получить доступ к данным, определённым в ColorContext , выполнив .
Чтобы сообщить React о намерении передать context от родительского компонента остальным его дочерним элементам, нужно определить два атрибута в родительском классе:
- childContextTypes,
- getChildContext.
Чтобы извлечь контекст внутри дочернего компонента, нужно определить в нём contextTypes .
Родительский компонент определяет context, который React использует для передачи данных глобально своим дочерним элементам.
Как теперь сделать так, чтобы дочерние элементы могли передавать данные своим родителям?
Дочерние компоненты могут изменять значение context, который будет отражаться во всех вложенных компонентах, включая и родительский компонент.
React-Redux/Redux
Это своего рода “ремейк” способа Context в React. Redux — это простая библиотека управления свойствами приложения, которая позволяет легко хранить эти свойства в одном месте и изменять их из любого места.
React-Redux был создан, чтобы сделать Redux легко совместимым с приложениями React.
Поскольку состояние определяется в одном месте, родительские компоненты могут устанавливать или обновлять его значение, а дочерние могут это фиксировать: связь Родитель-Наследник.
Аналогично дочерние компоненты могут устанавливать или обновлять значение состояния в хранилище, и оно также будет фиксироваться родительскими компонентами: связь Наследник-Родитель.
// . const initialState = < count: 0 >const countApp = function(state = initialState, action) < switch(action) < case 'ADD_COUNT': return return state > > const store = createStore(countApp) // Директория src/P.js class P extends React.Component < render() < return ( Count: ) > > /** * отправка maps в props **/ function mapDispatchToProps(dispatch) < return < updateCount: (count)=>< dispatch()> > > /** * maps передаёт свойство в props **/ function mapStateToProps(state) < return < count: state.count >> export default connect(mapStateToProps, mapDispatchToProps)(P) // Директория src/C.js class C extends React.Component < render() < return (
В этом фрагменте создаётся центральное хранилище, в котором содержится свойство count . P может обновить это свойство и дочерний компонент C получит его. Дочерний компонент также может обновить свойство count , и родительский компонент получит его.
Они могут подключиться к центральному хранилищу, объединившись в функцию connect(. ) , которая возвращает компонент высшего порядка.
Заключение
В этом материале вы увидели, как происходит взаимодействие между компонентами React и какими способами можно этого достичь:
- Родитель-наследник,
- Наследник-Родитель.
В первом разделе вы увидели использование props и render props, они работают с помощью HTML-подобных атрибутов. Context использует центральное хранилище, которое родитель и потомки могут как читать, так и обновлять. React-Redux и Redux делают то же самое, что и Context, компоненты выполняют чтение/запись из центрального хранилища.
Для дальнейшего освоения React вам может быть полезен данный материал.
Передача данных между компонентами в React
В реакте поток данных — однонаправленный. Это значит что данные передаются как водопад, сверху вниз, от родителя к ребенку, через props. Что такое props? Это неизменяемый объект, предназначенный только для чтения. Проще понять если думать о компонентах, как о функциях(а они по сути ими и являются), props—это просто аргумент функции, с которым мы можем работать внутри, но не изменять.
Родитель ➡️ Ребенок — используй Props
Это самый простой способ передачи данных.
1. В родительском компоненте передаём данные из стейта в дочерний.
2. В дочернем принимаем и выводим.
Props:
Родитель ⬅️ Ребенок — используй Callback
Эта передача данных напоминает мне бумеранг, есть точка старта — это наш родительский компонент, есть точка максимального отдаления — это дочерний компонент. И есть наш инструмент —бумеранг, в реакте это будет функция, которая находится в родителе и передаётся через props в ребенка, где и вызывается.
1. Создаём в родителе функцию updateData . У неё есть входной параметр value , этот параметр мы присваиваем в стейт нашего компонента, с помощью функции setState . Бумеранг готов!
updateData = (value) => this.setState(< name: value >)>
2. Передаём в дочерний элемент через props функцию updateData . Мы запустили бумеранг 🙂
3. В дочернем элементе я создала кнопку, при клике на неё будет вызываться функция, которую мы передавали с помощью props. Ей передается новый параметр для текста, именно его мы хотим передать в родителя. Бумеранг возвращается назад.
Ребенок ➡️ Ребенок—используй родителя.
Для того чтобы передать данные между соседними компонентами, нужно использовать посредника—их родителя. Сначала нужно передать данные от ребенка к родителю как аргумент коллбека. Потом присвоить эти данные в стейт родителя и передать через props другому компоненту.
как передать компонент в компонент react
Пример передачи компонента в другой компонент через свойство props :
function ParentComponent(props) return ( div> h1>Parent Componenth1> props.childComponent> div> ); > function ChildComponent() return p>Child Componentp>; > function App() const myComponent = ChildComponent />; return ParentComponent childComponent=myComponent> />; >
Здесь мы создаем компонент ParentComponent , который принимает props и рендерит свойство childComponent . Затем мы создаем компонент ChildComponent , который мы хотим передать в «ParentComponent».
В функции App мы создаем компонент «myComponent», который содержит ChildComponent , а затем передаем его в ParentComponent через свойство childComponent .
Таким образом, при рендеринге App мы увидим ParentComponent , который содержит ChildComponent .
Передача параметров¶
Компоненты React используют props для взаимодействия друг с другом. Каждый родительский компонент может передавать некоторую информацию своим дочерним компонентам, передавая им параметры. Параметры могут напомнить вам атрибуты HTML, но через них можно передавать любые значения JavaScript, включая объекты, массивы и функции.
- Как передать параметры компоненту
- Как читать параметры из компонента
- Как указать значения по умолчанию для параметров
- Как передать некоторый JSX в компонент
- Как параметры изменяются со временем
Известные параметры¶
Параметры — это информация, которую вы передаете в тег JSX. Например, className , src , alt , width и height — вот некоторые из параметров, которые вы можете передать тегу :
App.js Результат
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
function Avatar() return ( img className="avatar" src="https://i.imgur.com/1bX5QH6.jpg" alt="Lin Lanying" width=100> height=100> /> ); > export default function Profile() return Avatar />; >

Параметры, которые вы можете передать тегу , предопределены (ReactDOM соответствует стандарту HTML). Но вы можете передавать любые параметры своим компонентам, таким как , чтобы настроить их. Вот как!
Передача параметров компоненту¶
В этом коде компонент Profile не передает никаких параметров своему дочернему компоненту Avatar :
1 2 3
export default function Profile() return Avatar />; >
Вы можете передать Avatar некоторые параметры в два этапа.
Шаг 1: Передайте параметры дочернему компоненту¶
Сначала передайте Avatar некоторые параметры. Например, передадим два параметра: person (объект) и size (число):
1 2 3 4 5 6 7 8 9 10 11
export default function Profile() return ( Avatar person= <name: 'Lin Lanying', imageId: '1bX5QH6', >> size=100> /> ); >
Если двойные фигурные скобки после person= вас смущают, вспомните они просто объект внутри JSX-скобок.
Теперь вы можете прочитать эти параметры внутри компонента Avatar .
Шаг 2: Чтение параметров внутри дочернего компонента¶
Вы можете прочитать эти параметры, перечислив их имена person, size , разделенные запятыми внутри (< и >) непосредственно после функции Avatar . Это позволит вам использовать их внутри кода Avatar , как вы бы сделали это с переменной.
1 2 3
function Avatar( person, size >) // person and size are available here >
Добавьте в Avatar логику, которая использует параметры person и Size для рендеринга, и все готово.
Теперь вы можете настроить Avatar для рендеринга различными способами с различными параметрами. Попробуйте настроить значения!
App.js utils.js Результат
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
import getImageUrl > from './utils.js'; function Avatar( person, size >) return ( img className="avatar" src=getImageUrl(person)> alt=person.name> width=size> height=size> /> ); > export default function Profile() return ( div> Avatar size=100> person= <name: 'Katsuko Saruhashi', imageId: 'YfeOqp2', >> /> Avatar size=80> person= <name: 'Aklilu Lemma', imageId: 'OKS67lh', >> /> Avatar size=50> person= <name: 'Lin Lanying', imageId: '1bX5QH6', >> /> /div> ); >
1 2 3 4 5 6 7 8
export function getImageUrl(person, size = 's') return ( 'https://i.imgur.com/' + person.imageId + size + '.jpg' ); >

Параметры позволяют вам думать о родительских и дочерних компонентах независимо друг от друга. Например, вы можете изменить параметры person или Size внутри Profile без необходимости думать о том, как Avatar использует их. Аналогично, вы можете изменить, как Avatar использует эти параметры, не заглядывая в Profile .
Вы можете думать о параметрах как о «ручках», которые можно регулировать. Они выполняют ту же роль, что и аргументы для функций — фактически, параметр является единственным аргументом вашего компонента! Функции компонентов React принимают единственный аргумент — объект props :
1 2 3 4 5
function Avatar(props) let person = props.person; let size = props.size; // . >
Обычно вам не нужен весь объект props , поэтому вы деструктурируете его на отдельные параметры.
Не пропустите пару символов < и >внутри ( и ) при объявлении параметров:
1 2 3
function Avatar( person, size >) // . >
Этот синтаксис называется «деструктуризация» и эквивалентен чтению свойств из параметра функции:
1 2 3 4 5
function Avatar(props) let person = props.person; let size = props.size; // . >
Указание значения по умолчанию для параметра¶
Если вы хотите задать значение по умолчанию для параметра, когда значение не указано, вы можете сделать это с помощью деструктуризации, поместив = и значение по умолчанию сразу после параметра:
1 2 3
function Avatar( person, size = 100 >) // . >
Теперь, если /> отображается без свойства size , то size будет установлен в 100 .
Значение по умолчанию используется только в том случае, если параметр size отсутствует или если вы передали size= . Но если вы передадите size= или size= , значение по умолчанию не будет использоваться.
Пересылка параметров с синтаксисом JSX spread¶
Иногда передача параметров становится очень повторяющейся:
1 2 3 4 5 6 7 8 9 10 11 12
function Profile( person, size, isSepia, thickBorder >) return ( div className="card"> Avatar person=person> size=size> isSepia=isSepia> thickBorder=thickBorder> /> /div> ); >
Нет ничего плохого в повторяющемся коде — он может быть более разборчивым. Но иногда вам может быть важна краткость. Некоторые компоненты передают все свои параметры своим дочерним компонентам, например, как этот Profile делает это с Avatar . Поскольку они не используют параметры напрямую, имеет смысл использовать более лаконичный синтаксис «spread»:
1 2 3 4 5 6 7
function Profile(props) return ( div className="card"> Avatar props> /> /div> ); >
Это пересылает все параметры Profile в Avatar без перечисления имен каждого из них.
Используйте синтаксис распространения сдержанно. Если вы используете его в каждом втором компоненте, что-то не так. Часто это указывает на то, что вам следует разделить ваши компоненты и передавать дочерние компоненты как JSX. Подробнее об этом далее!
Передача JSX в качестве дочерних компонентов¶
Часто встречается вложение встроенных тегов браузера:
1 2 3
div> img /> /div>
Иногда вы захотите вложить свои собственные компоненты таким же образом:
1 2 3
Card> Avatar /> /Card>
Когда вы вложите содержимое в JSX-тег, родительский компонент получит это содержимое в свойстве children . Например, компонент Card ниже получит параметр children , установленный в , и отобразит его в обертке div:
App.js Avatar.js utils.js Результат
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
import Avatar from './Avatar.js'; function Card( children >) return div className="card">children>/div>; > export default function Profile() return ( Card> Avatar size=100> person= <name: 'Katsuko Saruhashi', imageId: 'YfeOqp2', >> /> /Card> ); >
1 2 3 4 5 6 7 8 9 10 11 12 13
import getImageUrl > from './utils.js'; export default function Avatar( person, size >) return ( img className="avatar" src=getImageUrl(person)> alt=person.name> width=size> height=size> /> ); >
1 2 3 4 5 6 7 8
export function getImageUrl(person, size = 's') return ( 'https://i.imgur.com/' + person.imageId + size + '.jpg' ); >

Попробуйте заменить внутри каким-нибудь текстом, чтобы увидеть, как компонент Card может обернуть любое вложенное содержимое. Ему не нужно «знать», что отображается внутри него. Вы увидите этот гибкий шаблон во многих местах.
Вы можете думать о компоненте с параметром children как о компоненте с «дырой», которая может быть «заполнена» его родительскими компонентами с помощью произвольного JSX. Вы часто будете использовать параметр children для визуальных оберток: панелей, сеток и т. д.

Как параметры меняются со временем¶
Компонент Clock ниже получает два параметра от своего родительского компонента: color и time . (Код родительского компонента опущен, поскольку он использует state, в который мы пока не будем углубляться).
Попробуйте изменить цвет в поле выбора ниже:
Clock.js App.js Результат
1 2 3
export default function Clock( color, time >) return h1 style= <color: color >>>time>/h1>; >
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
import useState, useEffect > from 'react'; import Clock from './Clock.js'; function useTime() const [time, setTime] = useState(() => new Date()); useEffect(() => const id = setInterval(() => setTime(new Date()); >, 1000); return () => clearInterval(id); >, []); return time; > export default function App() const time = useTime(); const [color, setColor] = useState('lightcoral'); return ( div> p> Pick a color:' '> select value=color> onChange=<(e) => setColor(e.target.value) > > option value="lightcoral"> lightcoral /option> option value="midnightblue"> midnightblue /option> option value="rebeccapurple"> rebeccapurple /option> /select> /p> Clock color=color> time=time.toLocaleTimeString()> /> /div> ); >

Этот пример иллюстрирует, что компонент может получать различные параметры с течением времени. параметры не всегда статичны! Здесь параметр time меняется каждую секунду, а параметр color меняется, когда вы выбираете другой цвет. параметры отражают данные компонента в любой момент времени, а не только в начале.
Однако параметры являются immutable- термин из информатики, означающий «неизменный». Когда компоненту нужно изменить свой параметр (например, в ответ на взаимодействие с пользователем или новые данные), он должен «попросить» свой родительский компонент передать ему другой параметр — новый объект! Его старые параметры будут отброшены, и в конечном итоге движок JavaScript вернет память, занятую ими.
Не пытайтесь «менять параметры». Когда вам нужно отреагировать на ввод пользователя (например, изменить выбранный цвет), вам нужно будет «установить состояние», о котором вы можете узнать в State: A Component’s Memory.
- Чтобы передать параметры, добавьте их в JSX, точно так же, как это делается с атрибутами HTML.
- Чтобы прочитать параметр, используйте синтаксис деструктуризации function Avatar(< person, size >) .
- Вы можете указать значение по умолчанию, например size = 100 , которое используется для отсутствующих и неопределенных параметров.
- Вы можете переслать все параметры с помощью /> Синтаксис распространения JSX, но не злоупотребляйте им!
- Вложенные JSX типа
будут отображаться как дочерние параметры компонента Card . - параметры — это снимки времени, доступные только для чтения: каждый рендер получает новую версию параметра.
- Вы не можете изменять параметры. Когда вам понадобится интерактивность, вам нужно будет установить состояние.
Задачи¶
1. Извлечение компонента¶
Этот компонент Gallery содержит очень похожую разметку для двух профилей. Извлеките из него компонент Profile , чтобы уменьшить дублирование. Вам нужно будет выбрать, какие параметры передать ему.
App.js utils.js Результат
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
import getImageUrl > from './utils.js'; export default function Gallery() return ( div> h1>Notable Scientists/h1> section className="profile"> h2>Maria Skłodowska-Curie/h2> img className="avatar" src=getImageUrl('szV5sdG')> alt="Maria Skłodowska-Curie" width=70> height=70> /> ul> li> b>Profession: /b> physicist and chemist /li> li> b>Awards: 4 /b> (Nobel Prize in Physics, Nobel Prize in Chemistry, Davy Medal, Matteucci Medal) /li> li> b>Discovered: /b> polonium (element) /li> /ul> /section> section className="profile"> h2>Katsuko Saruhashi/h2> img className="avatar" src=getImageUrl('YfeOqp2')> alt="Katsuko Saruhashi" width=70> height=70> /> ul> li> b>Profession: /b> geochemist /li> li> b>Awards: 2 /b> (Miyake Prize for geochemistry, Tanaka Prize) /li> li> b>Discovered: /b>a method for measuring carbon dioxide in seawater /li> /ul> /section> /div> ); >
1 2 3
export function getImageUrl(imageId, size = 's') return 'https://i.imgur.com/' + imageId + size + '.jpg'; >

Показать подсказку
Начните с извлечения разметки для одного из ученых. Затем найдите части, которые не соответствуют ему во втором примере, и сделайте их настраиваемыми с помощью параметров.
В этом решении компонент Profile принимает несколько параметров: imageId (строка), name (строка), profession (строка), awards (массив строк), discovery (строка) и imageSize (число).
Обратите внимание, что параметр imageSize имеет значение по умолчанию, поэтому мы не передаем его компоненту.
App.js utils.js Результат
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
import getImageUrl > from './utils.js'; function Profile( imageId, name, profession, awards, discovery, imageSize = 70, >) return ( section className="profile"> h2>name>/h2> img className="avatar" src=getImageUrl(imageId)> alt=name> width=imageSize> height=imageSize> /> ul> li> b>Profession:/b> /li> li> b>Awards: awards.length> /b>( awards.join(', ')>) /li> li> b>Discovered: /b> discovery> /li> /ul> /section> ); > export default function Gallery() return ( div> h1>Notable Scientists/h1> Profile imageId="szV5sdG" name="Maria Skłodowska-Curie" profession="physicist and chemist" discovery="polonium (chemical element)" awards= <['Nobel Prize in Physics', 'Nobel Prize in Chemistry', 'Davy Medal', 'Matteucci Medal', ]> /> Profile imageId="YfeOqp2" name="Katsuko Saruhashi" profession="geochemist" discovery="a method for measuring carbon dioxide in seawater" awards= <['Miyake Prize for geochemistry', 'Tanaka Prize', ]> /> /div> ); >
1 2 3
export function getImageUrl(imageId, size = 's') return 'https://i.imgur.com/' + imageId + size + '.jpg'; >

Обратите внимание, что вам не нужен отдельный параметр awardCount , если awards — это массив. Тогда вы можете использовать awards.length для подсчета количества наград. Помните, что параметр может принимать любые значения, в том числе и массивы тоже!
Другое решение, более похожее на предыдущие примеры на этой странице, заключается в том, чтобы сгруппировать всю информацию о человеке в одном объекте и передать этот объект как один параметр:
App.js utils.js Результат
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
import getImageUrl > from './utils.js'; function Profile( person, imageSize = 70 >) const imageSrc = getImageUrl(person); return ( section className="profile"> h2>person.name>/h2> img className="avatar" src=imageSrc> alt=person.name> width=imageSize> height=imageSize> /> ul> li> b>Profession:/b> /li> li> b>Awards: person.awards.length> /b>( person.awards.join(', ')>) /li> li> b>Discovered: /b> person.discovery> /li> /ul> /section> ); > export default function Gallery() return ( div> h1>Notable Scientists/h1> Profile person= <imageId: 'szV5sdG', name: 'Maria Skłodowska-Curie', profession: 'physicist and chemist', discovery: 'polonium (chemical element)', awards: [ 'Nobel Prize in Physics', 'Nobel Prize in Chemistry', 'Davy Medal', 'Matteucci Medal', ], >> /> Profile person= <imageId: 'YfeOqp2', name: 'Katsuko Saruhashi', profession: 'geochemist', discovery: 'a method for measuring carbon dioxide in seawater', awards: [ 'Miyake Prize for geochemistry', 'Tanaka Prize', ], >> /> /div> ); >
1 2 3 4 5 6 7 8
export function getImageUrl(person, size = 's') return ( 'https://i.imgur.com/' + person.imageId + size + '.jpg' ); >

Хотя синтаксис выглядит несколько иначе, поскольку вы описываете свойства объекта JavaScript, а не коллекцию атрибутов JSX, эти примеры в основном эквивалентны, и вы можете выбрать любой подход.
2. Настройте размер изображения на основе параметров¶
В этом примере Avatar получает числовой параметр size , который определяет ширину и высоту . В данном примере параметр size установлен на 40 . Однако если вы откроете изображение в новой вкладке, вы заметите, что само изображение больше ( 160 пикселей). Реальный размер изображения определяется тем, какой размер миниатюры вы запрашиваете.
Измените компонент Avatar , чтобы он запрашивал наиболее близкий размер изображения на основе параметра size . В частности, если size меньше 90 , передавайте ‘s’ («small»), а не ‘b’ («big») в функцию getImageUrl . Проверьте, что ваши изменения работают, отобразив аватары с разными значениями параметра size и открыв изображения в новой вкладке.
App.js utils.js Результат
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
import getImageUrl > from './utils.js'; function Avatar( person, size >) return ( img className="avatar" src=getImageUrl(person, 'b')> alt=person.name> width=size> height=size> /> ); > export default function Profile() return ( Avatar size=40> person= <name: 'Gregorio Y. Zara', imageId: '7vQD0fP', >> /> ); >
1 2 3 4 5 6 7 8
export function getImageUrl(person, size) return ( 'https://i.imgur.com/' + person.imageId + size + '.jpg' ); >

Показать решение
Вот как вы можете поступить:
App.js utils.js Результат
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
import getImageUrl > from './utils.js'; function Avatar( person, size >) let thumbnailSize = 's'; if (size > 90) thumbnailSize = 'b'; > return ( img className="avatar" src=getImageUrl(person, thumbnailSize)> alt=person.name> width=size> height=size> /> ); > export default function Profile() return ( <> Avatar size=40> person= <name: 'Gregorio Y. Zara', imageId: '7vQD0fP', >> /> Avatar size=120> person= <name: 'Gregorio Y. Zara', imageId: '7vQD0fP', >> /> /> ); >
1 2 3 4 5 6 7 8
export function getImageUrl(person, size) return ( 'https://i.imgur.com/' + person.imageId + size + '.jpg' ); >

Вы также можете показать более четкое изображение для экранов с высоким DPI, принимая во внимание window.devicePixelRatio :
App.js utils.js Результат
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
import getImageUrl > from './utils.js'; const ratio = window.devicePixelRatio; function Avatar( person, size >) let thumbnailSize = 's'; if (size * ratio > 90) thumbnailSize = 'b'; > return ( img className="avatar" src=getImageUrl(person, thumbnailSize)> alt=person.name> width=size> height=size> /> ); > export default function Profile() return ( <> Avatar size=40> person= <name: 'Gregorio Y. Zara', imageId: '7vQD0fP', >> /> Avatar size=70> person= <name: 'Gregorio Y. Zara', imageId: '7vQD0fP', >> /> Avatar size=120> person= <name: 'Gregorio Y. Zara', imageId: '7vQD0fP', >> /> /> ); >
1 2 3 4 5 6 7 8
export function getImageUrl(person, size) return ( 'https://i.imgur.com/' + person.imageId + size + '.jpg' ); >

Параметры позволяют инкапсулировать подобную логику внутри компонента Avatar (и изменить ее позже, если потребуется), чтобы каждый мог использовать компонент , не задумываясь о том, как запрашиваются и изменяются размеры изображений.
3. Передача JSX в children параметр¶
Извлеките компонент Card из приведенной ниже разметки и используйте параметр children для передачи ему различных JSX:
App.js Результат
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
export default function Profile() return ( div> div className="card"> div className="card-content"> h1>Photo/h1> img className="avatar" src="https://i.imgur.com/OKS67lhm.jpg" alt="Aklilu Lemma" width=70> height=70> /> /div> /div> div className="card"> div className="card-content"> h1>About/h1> p> Aklilu Lemma was a distinguished Ethiopian scientist who discovered a natural treatment to schistosomiasis. /p> /div> /div> /div> ); >

Показать подсказку
Любой JSX, который вы поместите внутрь тега компонента, будет передан в качестве параметра children этому компоненту.
Вот как вы можете использовать компонент Card в обоих местах:
App.js Результат
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
function Card( children >) return ( div className="card"> div className="card-content">children>/div> /div> ); > export default function Profile() return ( div> Card> h1>Photo/h1> img className="avatar" src="https://i.imgur.com/OKS67lhm.jpg" alt="Aklilu Lemma" width=100> height=100> /> /Card> Card> h1>About/h1> p> Aklilu Lemma was a distinguished Ethiopian scientist who discovered a natural treatment to schistosomiasis. /p> /Card> /div> ); >

Вы также можете сделать title отдельным параметром, если хотите, чтобы каждая Card всегда имела заголовок:
App.js Результат
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
function Card( children, title >) return ( div className="card"> div className="card-content"> h1>title>/h1> children> /div> /div> ); > export default function Profile() return ( div> Card title="Photo"> img className="avatar" src="https://i.imgur.com/OKS67lhm.jpg" alt="Aklilu Lemma" width=100> height=100> /> /Card> Card title="About"> p> Aklilu Lemma was a distinguished Ethiopian scientist who discovered a natural treatment to schistosomiasis. /p> /Card> /div> ); >
