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