Передача свойств компоненту
Компоненты React используют свойства (props) для взаимодействия друг с другом. Каждый родительский компонент может передать информацию своим дочерним компонентам, используя свойства. Свойства напоминают атрибуты HTML, но через них можно передавать любые значения JavaScript, включая объекты, массивы и функции.
Вы узнаете
- Как передавать свойства компоненту
- Как читать свойства из компонента
- Как задавать значения по умолчанию для свойств
- Как передавать JSX компоненту
- Как свойства изменяются со временем
Обычные свойства
Свойства — это информация, которую вы передаёте тегу JSX. Например, className, src, alt, width, и height — это некоторые свойства, которые можно передать в <img>:
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 /> ); }
Свойства, которые можно передать тегу <img>, предопределены (ReactDOM соответствует стандарту HTML). Но вы можете передавать любые свойства своим компонентам, таким как <Avatar>, чтобы настроить их. Вот как это сделать!
Передача свойств компоненту
В этом коде компонент Profile не передаёт никаких свойств своему дочернему компоненту Avatar:
export default function Profile() {
return (
<Avatar />
);
} Вы можете предоставить Avatar некоторые свойства в два шага.
Шаг 1: Передача свойств дочернему компоненту
Во-первых, передайте некоторые свойства в Avatar. Например, давайте передадим два свойства: person (объект) и size (число):
export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
} Примечание
Если двойные фигурные скобки после person= вас смущают, вспомните, что они просто представляют собой объект внутри фигурных скобок JSX.
Теперь вы можете прочитать эти свойства внутри компонента Avatar.
Шаг 2: Чтение свойств внутри дочернего компонента
Вы можете прочитать эти свойства, перечислив их имена person, size через запятые внутри ({ и }) сразу после function Avatar. Это позволяет использовать их внутри кода Avatar, как вы бы использовали переменную.
function Avatar({ person, size }) {
// person and size are available here
} Добавьте немного логики в Avatar, которая использует свойства person и size для рендеринга, и всё готово.
Теперь вы можете настроить Avatar для рендеринга различными способами с различными свойствами. Попробуйте изменить значения!
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> ); }
Свойства позволяют рассматривать родительские и дочерние компоненты независимо. Например, вы можете изменить свойства person или size внутри Profile, не задумываясь о том, как Avatar их использует. Аналогично, вы можете изменить то, как Avatar использует эти свойства, не глядя на Profile.
Можно представить свойства как «регуляторы», которые можно настраивать. Они выполняют ту же функцию, что и аргументы для функций — фактически, свойства и есть единственный аргумент вашего компонента! Функции компонентов React принимают единственный аргумент — объект props:
function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
} Обычно вам не нужен весь объект props целиком, поэтому вы деструктурируете его в отдельные свойства.
Опасность
Не пропустите пару { и } фигурных скобок внутри ( и ) при объявлении свойств:
function Avatar({ person, size }) {
// ...
}
Этот синтаксис называется «деструктуризацией» и эквивалентен чтению свойств из параметра функции:
function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}
Задание значения по умолчанию для свойства
Если вы хотите присвоить свойству значение по умолчанию, к которому можно обратиться, если значение не задано, вы можете сделать это с помощью деструктуризации, поместив = и значение по умолчанию сразу после параметра:
function Avatar({ person, size = 100 }) {
// ...
} Теперь, если <Avatar person={...} /> отрисовывается без свойства size, свойство size будет установлено в значение 100.
Значение по умолчанию используется только в том случае, если свойство size отсутствует или если вы передаёте size={undefined}. Но если вы передаёте size={null} или size={0}, значение по умолчанию не будет использоваться.
Передача свойств с помощью синтаксиса разброса JSX
Иногда передача свойств становится очень повторяющейся:
function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar
person={person}
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
} В повторяющемся коде нет ничего плохого — он может быть более понятным. Но иногда вы можете ценить краткость. Некоторые компоненты передают все свои свойства своим дочерним компонентам, как это делает Profile с Avatar. Поскольку они не используют свои свойства напрямую, может иметь смысл использовать более краткий синтаксис «разброса»:
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
} Это передаёт все свойства Profile компоненту Avatar без перечисления каждого имени.
Используйте синтаксис разброса с осторожностью. Если вы используете его в каждом компоненте, значит, что-то не так. Часто это означает, что вам следует разделить компоненты и передать дочерние элементы как JSX. Подробнее об этом далее!
Передача JSX в качестве дочерних элементов
Обычно вложены встроенные теги браузера:
<div>
<img />
</div> Иногда вы захотите вложить свои собственные компоненты таким же образом:
<Card>
<Avatar />
</Card> Когда вы вкладываете контент внутри тега JSX, родительский компонент получит этот контент в свойстве с именем children. Например, компонент Card ниже получит свойство children со значением <Avatar /> и отобразит его в оболочке div:
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> ); }
Попробуйте заменить <Avatar> внутри <Card> некоторым текстом, чтобы увидеть, как компонент Card может оборачивать любой вложенный контент. Ему не нужно «знать», что рендерится внутри него. Вы увидите эту гибкую схему во многих местах.
Вы можете рассматривать компонент со свойством children как имеющий «дыру», которую родительские компоненты могут «заполнить» произвольным JSX. Вы часто будете использовать свойство children для визуальных оболочек: панелей, сеток и т.д.
Изображение предоставлено Rachel Lee Nabors
Как свойства изменяются со временем
Компонент Clock ниже получает два свойства от родительского компонента: color и time (код родительского компонента опущен, так как он использует состояние, которое мы пока не будем рассматривать).
Попробуйте изменить цвет в раскрывающемся списке:
export default function Clock({ color, time }) { return ( <h1 style={{ color: color }}> {time} </h1> ); }
Этот пример иллюстрирует, что компонент может получать разные свойства со временем. Свойства не всегда статичны! Здесь свойство time изменяется каждую секунду, а свойство color изменяется при выборе другого цвета. Свойства отражают данные компонента в любой момент времени, а не только в самом начале.
Однако свойства являются неизменяемыми — термин из информатики, означающий «неизменяемый». Когда компоненту нужно изменить свои свойства (например, в ответ на взаимодействие пользователя или новые данные), ему нужно «попросить» родительский компонент передать ему другие свойства — новый объект! Его старые свойства затем будут отброшены, и в конечном итоге движок JavaScript освободит занимаемую ими память.
Не пытайтесь «изменить свойства». Когда вам нужно отреагировать на ввод пользователя (например, изменить выбранный цвет), вам нужно будет «установить состояние», о котором вы можете узнать в Состояние: Память компонента.
Обзор
- Для передачи свойств добавьте их в JSX, как вы делаете с атрибутами HTML.
- Для чтения свойств используйте синтаксис деструктуризации
function Avatar({ person, size }). - Вы можете указать значение по умолчанию, например,
size = 100, которое используется для отсутствующих иundefinedсвойств. - Вы можете передать все свойства с помощью синтаксиса разброса JSX
<Avatar {...props} />, но не злоупотребляйте им! - Вложенный JSX, например,
<Card><Avatar /></Card>, будет отображаться как свойствоCardкомпонентаchildren. - Свойства — это моментальные снимки во времени: каждый рендеринг получает новую версию свойств.
- Вы не можете изменить свойства. Когда вам нужно взаимодействие, вам нужно установить состояние.
Попробуйте решить несколько задач
Задача 1 из 3:
Извлечь компонент
Этот Gallery компонент содержит очень похожий разметку для двух профилей. Извлеките Profile компонент из него, чтобы уменьшить дублирование. Вам нужно будет выбрать, какие свойства передать ему.
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 (chemical 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> ); }
© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://18.react.dev/learn/passing-props-to-a-component