Spec-Zone.ru › React 18

Условное рендерирование

Вашим компонентам часто необходимо отображать разные вещи в зависимости от разных условий. В React вы можете условно рендерить JSX, используя синтаксис JavaScript, например, if операторы, &&, и ? :.

Вы узнаете

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

Условное возвращение JSX

Предположим, у вас есть PackingList компонент, рендерящий несколько Item элементов, которые могут быть помечены как упакованные или нет:

function Item({ name, isPacked }) {
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Обратите внимание, что некоторые из Item компонентов имеют свойство isPacked установленное в значение true, а не в false. Вы хотите добавить галочку (✅) к упакованным элементам, если isPacked={true}.

Вы можете записать это как оператор if/else, так:

if (isPacked) {
  return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;

Если свойство isPacked имеет значение true, этот код возвращает другое дерево JSX. С этим изменением некоторые элементы получают галочку в конце:

function Item({ name, isPacked }) {
  if (isPacked) {
    return <li className="item">{name} ✅</li>;
  }
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Попробуйте изменить возвращаемое значение в любом случае и посмотрите, как изменится результат!

Обратите внимание, как вы создаёте логику ветвления с помощью операторов JavaScript if и return. В React поток управления (например, условия) обрабатывается JavaScript.

Условное возвращение ничего с null

В некоторых ситуациях вы вообще не захотите рендерить ничего. Например, предположим, что вы не хотите отображать упакованные элементы вообще. Компонент должен что-то возвращать. В этом случае вы можете вернуть null:

if (isPacked) {
  return null;
}
return <li className="item">{name}</li>;

Если isPacked истинно, компонент не вернёт ничего, null. В противном случае он вернёт JSX для рендеринга.

function Item({ name, isPacked }) {
  if (isPacked) {
    return null;
  }
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

На практике возвращение null из компонента не является распространённым случаем, так как это может удивить разработчика, пытающегося его рендерить. Чаще вы условно включаете или исключаете компонент в JSX родительского компонента. Вот как это сделать!

Условное включение JSX

В предыдущем примере вы контролировали, какое (если есть!) дерево JSX будет возвращено компонентом. Вы, возможно, уже заметили некоторую дублирование в выходных данных рендера:

<li className="item">{name} ✅</li>

очень похоже на

<li className="item">{name}</li>

Оба условных ветвления возвращают <li className="item">...</li>:

if (isPacked) {
  return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;

Хотя это дублирование не вредно, оно может затруднить поддержку вашего кода. А что, если вы хотите изменить className? Вам придётся изменить это в двух местах в вашем коде! В такой ситуации вы можете условно включить немного JSX, чтобы сделать ваш код более DRY.

Условный (тройной) оператор (? :)

В JavaScript есть компактный синтаксис для записи условного выражения — условный оператор или «тройной оператор».

Вместо этого:

if (isPacked) {
  return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;

Вы можете написать это:

return (
  <li className="item">
    {isPacked ? name + ' ✅' : name}
  </li>
);

Вы можете прочитать это как «если isPacked истинно, то (?) отобразить name + ' ✅', в противном случае (:) отобразить name».

Подробное рассмотрение

Являются ли эти два примера полностью эквивалентными?

Если вы знакомы с объектно-ориентированным программированием, вы можете предположить, что два примера выше немного отличаются, потому что один из них может создать два разных «экземпляра» <li>. Но элементы JSX не являются «экземплярами», потому что они не хранят внутреннее состояние и не являются реальными узлами DOM. Они являются лёгкими описаниями, как чертежи. Поэтому эти два примера, на самом деле, полностью эквивалентны. Сохранение и сброс состояния подробно описывает, как это работает.

Теперь предположим, что вы хотите обернуть текст завершённого элемента в другой HTML-тег, например, <del> для его перечёркивания. Вы можете добавить ещё больше новых строк и скобок, чтобы было легче вкладывать JSX в каждый из случаев:

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {isPacked ? (
        <del>
          {name + ' ✅'}
        </del>
      ) : (
        name
      )}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

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

Логический оператор И (&&)

Другое часто используемое сокращение — это логический оператор И JavaScript (&& оператор). Внутри компонентов React он часто возникает, когда вы хотите отобразить JSX, когда условие истинно, или не отображать ничего иначе. С &&, вы могли бы условно отобразить галочку только в том случае, если isPacked имеет значение true:

return (
  <li className="item">
    {name} {isPacked && '✅'}
  </li>
);

Вы можете прочитать это как «если isPacked, то (&&) отобразить галочку, иначе отобразить ничего».

Вот как это работает на практике:

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✅'}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Выражение JavaScript && возвращает значение своей правой части (в нашем случае, галочка) если левая часть (наше условие) истинна. Но если условие ложно, всё выражение становится false. React рассматривает false как «дыру» в дереве JSX, так же как null или undefined, и ничего не отображает на её месте.

Опасность

Не помещайте числа в левую часть оператора &&.

Для проверки условия JavaScript автоматически преобразует левую часть в булево значение. Однако, если левая часть равна 0, всё выражение получает это значение (0), и React отобразит 0 вместо ничего.

Например, распространённой ошибкой является запись кода, такого как messageCount && <p>New messages</p>. Легко предположить, что он отображает ничего, когда messageCount имеет значение 0, но на самом деле он отображает 0!

Чтобы исправить это, сделайте левую часть булевой: messageCount > 0 && <p>New messages</p>.

Условное присвоение JSX переменной

Когда сокращения мешают вам писать простой код, попробуйте использовать оператор if и переменную. Вы можете переопределять переменные, определённые с помощью let, поэтому начните с предоставления значения по умолчанию, которое вы хотите отобразить, имя:

let itemContent = name;

Используйте оператор if для переопределения выражения JSX на itemContent если isPacked имеет значение true:

if (isPacked) {
  itemContent = name + " ✅";
}

Фигурные скобки открывают «окно в JavaScript». Вставьте переменную в фигурные скобки в возвращаемом дереве JSX, вложив ранее вычисленное выражение внутрь JSX:

<li className="item">
  {itemContent}
</li>

Этот стиль является самым объёмным, но также и самым гибким. Вот как это работает на практике:

function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = name + " ✅";
  }
  return (
    <li className="item">
      {itemContent}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Как и прежде, это работает не только для текста, но и для произвольного JSX:

function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = (
      <del>
        {name + " ✅"}
      </del>
    );
  }
  return (
    <li className="item">
      {itemContent}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Если вы не знакомы с JavaScript, этот набор стилей может показаться изначально сложным. Однако изучение их поможет вам читать и писать любой JavaScript-код, а не только компоненты React! Выберите тот, который вам нравится, а затем снова обратитесь к этой справке, если забудете, как работают другие.

Заключение

  • В React вы управляете логикой ветвления с помощью JavaScript.
  • Вы можете условно вернуть выражение JSX с помощью оператора if.
  • Вы можете условно сохранить JSX в переменную и затем включить его внутри другого JSX, используя фигурные скобки.
  • В JSX, {cond ? <A /> : <B />} означает «если cond, отобразить <A />, иначе <B />».
  • В JSX, {cond && <A />} означает «если cond, отобразить <A />, иначе ничего».
  • Сокращения являются распространёнными, но вы не обязаны их использовать, если предпочитаете обычный if.

Попробуйте решить несколько задач

Задача 1 из 3:
Отобразить значок для незавершенных элементов с ? :

Используйте условный оператор (cond ? a : b) для отображения ❌, если isPacked не true.

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✅'}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://18.react.dev/learn/conditional-rendering

Spec-Zone.ru

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