Интерфейс часто зависит от данных: гостю — кнопка «Войти», пользователю — его имя; пустой корзине — ничего, полной — значок с числом. Это и есть условный рендер: показать одно, другое или ничего.
Внутрь JSX if не вставить — фигурные скобки принимают только выражения. Но
у JavaScript хватает выражений для условий, а if прекрасно работает до
return.
if до return
Самый прямой способ — выбрать, что вернуть, обычным if:
function Greeting({ user }) {
if (user) {
return <p>Здравствуйте, {user.name}!</p>
}
return <button>Войти</button>
}Удобно, когда варианты сильно отличаются. Если же меняется только кусочек разметки, повторять всё остальное дважды не хочется — тогда условие пишут прямо в JSX.
Тернарный оператор: одно или другое
условие ? это : то — выражение, поэтому его можно вставить в фигурные
скобки:
function Status({ online }) {
return <p>Статус: {online ? 'в сети' : 'не в сети'}</p>
}Ветки могут быть и разметкой:
<div>
{user ? <p>Привет, {user.name}</p> : <button>Войти</button>}
</div>Если ветки длинные, заверните каждую в круглые скобки и разнесите по
строкам. Вложенные тернарники (a ? x : b ? y : z) читаются плохо —
лучше вынести выбор в переменную до return.
&& : показать или ничего
Часто вторая ветка не нужна: есть сообщение — показать, нет — ничего. Для
этого есть &&:
function Inbox({ unread }) {
return (
<div>
<h2>Входящие</h2>
{unread > 0 && <p>Новых писем: {unread}</p>}
</div>
)
}Работает это так: a && b возвращает a, если оно ложное, иначе b. А
ложные false, null и undefined React просто не рисует. Получается:
условие истинно — на экране абзац, ложно — пусто.
Ловушка: 0 &&
Не всё ложное React пропускает. Число 0 он рисует, как любое число:
function Cart({ count }) {
return <div>Корзина {count && <span>{count}</span>}</div>
}
<Cart count={3} /> // Корзина 3 — как и задумано
<Cart count={0} /> // Корзина 0 — откуда ноль?!При count = 0 выражение count && … вернуло сам 0, и React его
нарисовал. С пустой строкой '' та же история, только её не видно.
Лекарство — слева от && ставить настоящее true/false:
{count > 0 && <span>{count}</span>}
{items.length > 0 && <List items={items} />}
{Boolean(message) && <p>{message}</p>}Привычка «слева от && — сравнение» спасёт от этой ошибки навсегда.
return null: не рисовать ничего
Компонент может решить, что показывать нечего, и вернуть null. React
ничего не нарисует — ни обёртки, ни пустого тега:
function Warning({ text }) {
if (!text) {
return null
}
return <div className="warning">{text}</div>
}
<Warning text="" /> // ничего
<Warning text="Осторожно" /> // <div className="warning">Осторожно</div>Такой ранний выход удобен в начале компонента: отсекли особый случай — и дальше пишете основную разметку без лишних условий.
Класс по условию
className — тоже выражение, значит, его можно выбрать тернарником:
function Task({ title, done }) {
return <li className={done ? 'task done' : 'task'}>{title}</li>
}Или собрать из кусочков шаблонной строкой:
<button className={`btn ${primary ? 'btn-primary' : 'btn-plain'}`}>
{text}
</button>Следите за пробелами: 'btn' + 'btn-primary' даст один класс btnbtn-primary.
Какой способ выбрать
- два разных результата целиком —
ifи дваreturn; - нечего показывать вообще —
return nullв начале; - одно из двух внутри разметки —
? :; - кусок есть или нет —
&&со сравнением слева; - разные классы — тернарник в
className.
Все они дают одно и то же: обычный JSX, который React нарисует. Выбирайте тот, что проще читается.