Spec-Zone.ru › React

Условный вывод

Вашим компонентам часто нужно отображать разные вещи в зависимости от различных условий. В 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 (JavaScript logical AND (&&) оператор).

Внутри компонентов 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://react.dev/learn/conditional-rendering

Spec-Zone.ru

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