Условный рендеринг
Вашим компонентам часто приходится отображать разные элементы в зависимости от различных условий. В 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> );}Попробуйте изменить то, что возвращается в каждом из случаев, и посмотрите, как изменится результат!
Обратите внимание, как вы создаете логику ветвления с помощью операторов if и return в JavaScript. В React управление потоком (например, условия) обрабатывается JavaScript.
Условное возвращение null
В некоторых ситуациях вам не захочется отображать ничего вообще. Например, предположим, вы не хотите показывать упакованные предметы. Компонент должен что-то возвращать. В этом случае вы можете вернуть null:
if (isPacked) {
return null;
}
return <li className="item">{name}</li>;Если isPacked равно true, компонент не вернет ничего, то есть 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 равно true, то (?) отобразить 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 разметка является частью вашего кода, поэтому вы можете использовать такие инструменты, как переменные и функции, для упорядочивания сложных выражений.
Логический оператор AND (&&)
Еще одним распространенным сокращением, с которым вы столкнетесь, является логический оператор AND (&&) в 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 && возвращает значение правой части (в нашем случае галочку), если левая часть (наше условие) равна true. Но если условие равно false, все выражение становится 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.
Передача пропсов в компонент
Компоненты React используют *пропсы* для взаимодействия друг с другом. Каждый родительский компонент может передавать некоторую информацию своим дочерним компонентам, предоставляя им пропсы. Пропсы могут напоминать атрибуты HTML, но через них можно передавать любые значения JavaScript, включая объекты, массивы и функции.
Рендеринг списков
Часто возникает необходимость отобразить несколько похожих компонентов из набора данных. Для работы с массивом данных можно использовать методы массивов JavaScript. На этой странице вы будете использовать filter() и map() с React для фильтрации и преобразования массива данных в массив компонентов.