Spec-Zone.ru › React

Передача свойств компоненту

Компоненты React используют свойства для взаимодействия друг с другом. Каждый родительский компонент может передать некоторую информацию своим дочерним компонентам, предоставив им свойства. Свойства могут напомнить вам атрибуты 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 spread

Иногда передача свойств становится очень повторяющейся:

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 для визуальных оболочек: панелей, сетки и т. д.

A puzzle-like Card tile with a slot for "children" pieces like text and Avatar

Иллюстрировано Рэйчел Ли Наборс

Как свойства изменяются со временем

Компонент 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 spread <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://react.dev/learn/passing-props-to-a-component

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API