Как передать пропсы React компоненту

год назад·5 мин. на чтение

Компоненты React используют пропсы (props) для связи друг с другом. Каждый родительский компонент может передавать некоторую информацию своим дочерним компонентам, предоставляя им пропсы. Пропсы могут напоминать атрибуты HTML, но вы можете передавать через них любое значение JavaScript, включая объекты, массивы и функции.

Содержание туториала по React Компоненты React используют пропсы (props) для связи друг с другом. Каждый родительский компонент может передавать некоторую информацию своим дочерним компонентам, предоставляя им пропсы. Пропсы могут напоминать атрибуты HTML, но вы можете передавать через них любое значение JavaScript, включая объекты, массивы и функции.

Известные пропсы

Пропсы — это информация, которую вы передаете тегу JSX. Например, className, src, alt, width и height — вот некоторые пропсы, которые вы можете передать <img>:
function Avatar() {
  return (
    <img
      className="avatar"
      src="https://example.com/userpic.jpg"
      alt="Userpic"
      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: 'User Name 1', imageId: '12345' }} size={100} />
  );
}
Если двойные фигурные скобки после person= вас смущают, помните, что они являются просто объектом внутри фигурных скобок JSX. Теперь вы можете прочитать эти пропсы внутри компонента Avatar.

Шаг 2: Прочтите пропсы внутри дочернего компонента

Вы можете прочитать эти пропсы, указав их имена - person, size - разделенные запятыми внутри ({ и }) непосредственно после function Avatar. Это позволяет использовать их внутри кода Avatar, как если бы вы использовали переменную.
function Avatar({ person, size }) {
  // person и size можно здесь использовть
}
Добавьте немного логики в Avatar, которая использует пропсы person, size в отображении, и все готово. Теперь вы можете настроить Avatar для отображения разными способами с разными пропсы.
// utils.js

export function getImageUrl(person, size = 's') {
  return 'https://example.com/' + person.imageId + size + '.jpg';
}
// App.js

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: 'User Name 1',
          imageId: '12345',
        }}
      />
      <Avatar
        size={80}
        person={{
          name: 'User Name 2',
          imageId: '12346',
        }}
      />
      <Avatar
        size={50}
        person={{
          name: 'User Name 3',
          imageId: '12347',
        }}
      />
    </div>
  );
}
Пропсы позволяют вам думать о родительских и дочерних компонентах независимо друг от друга. Например, вы можете изменить пропсы person или size внутри Profile, не задумываясь о том, как Avatar их использует. Точно так же вы можете изменить то, как Avatar использует эти пропсы, не заглядывая в Profile. Вы можете думать о пропсах как о «ручках», которые вы можете регулировать. Они выполняют ту же роль, что и аргументы для функций — на самом деле пропсы являются единственным аргументом для вашего компонента. Функции компонента React принимают один аргумент, объект props:
function Avatar(props) {
  let person = props.person;
  let size = props.size;
  // ...
}
Обычно вам не нужен весь объект пропса, поэтому можно разбить его на отдельные пропсы. Не пропустите пару фигурных скобок { и } внутри ( и ) при объявлении пропсов:
function Avatar({ person, size }) {
  // ...
}
Этот синтаксис называется «деструктурированием» и эквивалентен чтению свойств из параметра функции:
function Avatar(props) {
  let person = props.person;
  let size = props.size;
  // ...
}

Как указать значения по умолчанию для пропса

Если вы хотите присвоить пропсу значение по умолчанию, чтобы использовать его, когда значение не указано, вы можете сделать это с помощью деструктуризации, поставив = и значение по умолчанию сразу после параметра:
function Avatar({ person, size = 100 }) {
  // ...
}
Теперь, если в <Avatar person={...} /> передан пропс 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. Поскольку они не используют никакие свои пропсы напрямую, может иметь смысл использовать более краткий синтаксис распыления (spread):
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:
// App.js

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: 'User Name',
          imageId: '12345',
        }}
      />
    </Card>
  );
}
// Avatar.jsx

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}
    />
  );
}
// utils.js

export function getImageUrl(person, size = 's') {
  return 'https://example.com/' + person.imageId + size + '.jpg';
}
Вы можете думать о компоненте с пропсом children как о специальной лозейке, которую можно «заполнить» родительскими компонентами с произвольным JSX. Вы часто будете использовать проп children для визуальных оболочек: панелей, сеток и т.д.

Как пропсы меняются со временем

Компонент 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, которое используется для отсутствующих и неопределенных пропсов.
  • Вы можете перенаправить все пропсы с помощью синтаксиса распыления JSX <Avatar {...props} />, но не злоупотребляйте им.
  • Вложенный JSX, такой как <Card><Avatar /></Card>, будет отображаться как проп children компонента Card.
  • Пропсы - доступны только для чтения. Это такой снимок компонента во времени: каждый рендер получает новую версию пропса.
  • Нельзя менять пропсы внутри компонента. Когда вам нужна интерактивность, вам нужно установить состояние.

Как senior разработчики создают React приложения

2 года назад·3 мин. на чтение

В этой статье мы рассмотрим ключевые стратегии, которые senior разработчики используют для создания мощных и эффективных React приложений. Мы рассмотрим основные принципы React, рекомендации по структурированию и организации кода, а также инструменты и методы, которые могут помочь вам оптимизировать производительность и масштабируемость вашего приложения.

React, благодаря своим мощным возможностям для создания динамических, интерактивных веб-приложений, стал одним из самых популярных и широко используемых JavaScript-фреймворков в последние годы. Senior разработчики, имеющие опыт работы в React, имеют глубокое понимание основных принципов и лучших практик фреймворка, а также инструментов и методов, необходимых для создания масштабируемого, поддерживаемого кода. Независимо от того, являетесь ли вы опытным разработчиком React или только начинаете, понимание этих стратегий может помочь вам вывести свои навыки на новый уровень и создавать эффективные и элегантные приложения. Итак, давайте углубимся и подробнее рассмотрим, как Senior разработчики создают приложения на React.

Основные принципы React

В основе React лежит набор основных принципов. Понимание этих принципов является ключом к созданию масштабируемых, поддерживаемых приложений React. Одним из наиболее фундаментальных принципов React является концепция «однонаправленного потока данных». Это означает, что данные проходят через приложение в одном направлении, от родительских компонентов до дочерних компонентов. Структурируя приложение таким образом, можно создать четкий и предсказуемый поток данных, упрощающий управление кодом и его отладку. Другим основным принципом React является использование «виртуальной модели DOM» (Document Object Model). Виртуальный DOM представляет собой абстракцию собственной модели DOM браузера, которая позволяет React более эффективно обновлять пользовательский интерфейс, сводя к минимуму количество требуемых фактических обновлений DOM. Используя виртуальный DOM, React может обновлять пользовательский интерфейс быстрым и отзывчивым способом, не требуя ненужных повторных отрисовок или обновлений.

Рекомендации по структурированию и организации кода

Создание масштабируемых, поддерживаемых приложений на React требует тщательного планирования и организации. Вот некоторые рекомендации, которые следует иметь в виду:

Компонентная архитектура

Одним из ключевых преимуществ React является его компонентная архитектура. Разбивая приложение на многократно используемые модульные компоненты, можно создать более гибкую и поддерживаемую кодовую базу. Каждый компонент должен нести четкую и конкретную ответственность и должен быть спроектирован таким образом, чтобы быть как можно более автономным.

Разделение ответственности

Другим важным принципом создания поддерживаемых приложений React является разделение ответственности. Это означает разделение кода на отдельные слои, каждый из которых имеет свои собственные обязанности. Например, у вас может быть слой данных, который обрабатывает выборку данных и манипулирование ими, уровень представления, который обрабатывает отрисовку пользовательского интерфейса, и уровень контейнера, который управляет взаимодействием между ними.

Повторное использование кода

Повторное использование кода является еще одной ключевой стратегией создания масштабируемых приложений React. Повторно используя код везде, где это возможно, можно уменьшить дублирование и повысить общую эффективность кодовой базы. Это может включать в себя создание повторно используемых компонентов или абстрагирование общей функциональности в служебные функции или библиотеки.

Масштабируемая структура папок

Наконец, организация кода в масштабируемую структуру папок может помочь вам более эффективно управлять кодовой базой. Это может включать группирование связанных компонентов или модулей в отдельные каталоги или использование соглашения об именовании, которое упрощает поиск определенных файлов или компонентов. В статьях Структура React приложения, Архитектура современного React приложения подробно описаны варианты масштабируемых структур React проектов.

Инструменты и методы оптимизации производительности и масштабируемости

Даже при тщательном планировании и организации создание масштабируемых, производительных приложений React может быть сложной задачей. Вот некоторые инструменты и методы, которые могут помочь вам оптимизировать производительность и масштабируемость вашего приложения.

Рендеринг на стороне сервера

Отрисовка на стороне сервера (SSR) может помочь сократить время начальной загрузки приложения, отрендерив исходный HTML-код на сервере, а не ожидая, пока клиент загрузит и запустит JavaScript. Это может привести к более быстрому взаимодействию с пользователем, особенно в более медленных сетях или устройствах.

Разделение кода

Разделение кода — это метод, который включает в себя разбивку кода на более мелкие, более управляемые куски и загрузку их только тогда, когда они необходимы. Это может помочь сократить время начальной загрузки приложения и повысить общую производительность за счет уменьшения объема ненужного кода, который необходимо загрузить и выполнить.

Мемоизация

Мемоизация — это метод кэширования результатов дорогостоящих вычислений и их повторного использования при повторном предоставлении тех же входных данных. В контексте React это может быть особенно полезно для оптимизации производительности сложных или дорогостоящих компонентов, предотвращая ненужные повторные рендеры или обновления.

Профилирование производительности

Средства профилирования производительности могут помочь вам определить узкие места производительности в вашем приложении и оптимизировать их для повышения производительности. Эти средства могут предоставить подробную информацию о том, как работает ваше приложение, и помочь вам определить области, в которых требуется оптимизация.

Автоматизированное тестирование

Наконец, автоматизированное тестирование является важным инструментом для обеспечения того, чтобы ваше приложение React работало должным образом. Создавая автоматические тесты, которые охватывают все функциональные возможности вашего приложения, вы можете обнаружить потенциальные проблемы на ранней стадии и убедиться, что ваше приложение всегда работает правильно.