Умовний рендеринг
Ваші компоненти часто матимуть потребу відображати різні речі в залежності від різних умов. У React ви можете умовно рендерити JSX, використовуючи синтаксис JavaScript: оператори if
, &&
та ? :
.
You will learn
- Як повертати різний 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)</h1> <ul> <Item isPacked={true} name="Космічний костюм" /> <Item isPacked={true} name="Шолом із золотим листям" /> <Item isPacked={false} name="Фото Тем О'Шонессі(Tam O'Shaughnessy)" /> </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)</h1> <ul> <Item isPacked={true} name="Космічний костюм" /> <Item isPacked={true} name="Шолом із золотим листям" /> <Item isPacked={false} name="Фото Тем О'Шонессі(Tam O'Shaughnessy)" /> </ul> </section> ); }
Спробуйте змінити що повертає цей код в обох випадках та подивіться, як змінюється результат!
Зверніть увагу на те, як ви створюєте розгалужену логіку з JavaScript if
та return
виразами. У 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)</h1> <ul> <Item isPacked={true} name="Космічний костюм" /> <Item isPacked={true} name="Шолом із золотим листям" /> <Item isPacked={false} name="Фото Тем О'Шонессі(Tam O'Shaughnessy)" /> </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
”.
Deep Dive
Якщо у вас є досвід з об’єктно-орієнтованого програмування, ви можете припустити, що два приклади вище є трохи різними, оскільки один з них може створити дві різні “сутності” <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)</h1> <ul> <Item isPacked={true} name="Космічний костюм" /> <Item isPacked={true} name="Шолом із золотим листям" /> <Item isPacked={false} name="Фото Тем О'Шонессі(Tam O'Shaughnessy)" /> </ul> </section> ); }
Цей стиль добре працює для простих умов, але використовуйте його з розумом. Якщо ваші компоненти стають заплутаними через велику вкладену умовну розмітку, подумайте над “розпакуванням” дочірніх компонентів, щоб все виглядало охайніше. У React розмітка є частиною вашого коду, тому ви можете використовувати такі інструменти, як змінні та функції, щоб спростити складні вирази.
Логічний оператор AND (&&
)
Ще одне поширене скорочення, з яким ви зіткнетеся — логічний оператор AND (&&
) JavaScript. Всередині компонентів React він часто з’являється, коли ви хочете відрендерити деякий JSX, коли умова є true
, або нічого не рендерити в іншому випадку. З &&
ви могли б умовно відрендерити позначку, лише якщо 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)</h1> <ul> <Item isPacked={true} name="Космічний костюм" /> <Item isPacked={true} name="Шолом із золотим листям" /> <Item isPacked={false} name="Фото Тем О'Шонессі(Tam O'Shaughnessy)" /> </ul> </section> ); }
JavaScript && вираз повертає значення своєї правої сторони (у нашому випадку, позначку) якщо ліва сторона (наша умова) true
. Але якщо умова false
, то весь вираз стає false
. React розглядає false
як “діру” в JSX дереві, так само як null
або undefined
, і не рендерить нічого на його місці.
Умовне присвоєння JSX змінній
Коли скорочення заважають писати звичайний код, спробуйте використати оператор if
та змінну. Ви можете переприсвоювати змінні, визначені за допомогою let
, тому почніть з задання вмісту за замовчуванням, який ви хочете відобразити, name:
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)</h1> <ul> <Item isPacked={true} name="Космічний костюм" /> <Item isPacked={true} name="Шолом із золотим листям" /> <Item isPacked={false} name="Фото Тем О'Шонессі(Tam O'Shaughnessy)" /> </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)</h1> <ul> <Item isPacked={true} name="Космічний костюм" /> <Item isPacked={true} name="Шолом із золотим листям" /> <Item isPacked={false} name="Фото Тем О'Шонессі(Tam O'Shaughnessy)" /> </ul> </section> ); }
Якщо ви не знайомі з JavaScript, то ця різноманітність стилів може спершу здатися вам занадто складною. Однак, їх знання допоможе вам читати та писати будь-який код JavaScript — і не тільки компоненти React! Виберіть той, який вам більше подобається для початку, а потім зверніться до цього довідника знову, якщо ви забудете, як працюють інші.
Recap
- У React ви керуєте розгалуженою логікою за допомогою JavaScript.
- Ви можете повернути JSX-вираз умовно за допомогою оператора
if
. - Ви можете умовно зберегти деякий JSX у змінну, а потім включити його в інший JSX, використовуючи фігурні дужки.
- У JSX,
{cond ? <A /> : <B />}
означає “якщоcond
, відобразити<A />
, інакше<B />
”. - У JSX,
{cond && <A />}
означає “якщоcond
, відобразити<A />
, інакше нічого”. - Ці скорочення є поширеними, але ви не повинні їх використовувати, якщо вам більше подобається простий
if
.
Challenge 1 of 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)</h1> <ul> <Item isPacked={true} name="Космічний костюм" /> <Item isPacked={true} name="Шолом із золотим листям" /> <Item isPacked={false} name="Фото Тем О'Шонессі(Tam O'Shaughnessy)" /> </ul> </section> ); }