Условный рендеринг
Вашим компонентам нужно часто отображать различные вещи в зависимости от различных условий. В React вы можете рендерить JSX в зависимости от его условий, используя JavaScript операторы. Такие, как if
, &&
и ? :
You will learn
- Как вернуть разный JSX, в зависимости от условия.
- Как в зависимости от условий добавить или убрать часть JSX.
- Часто встречающиеся сокращения синтаксиса условных выражений, с которыми вы столкнётесь в проектах на React.
Условный возврат JSX
Допустим, у вас есть компонент PackingList
, который рендерит несколько компонентов Item
, который могут быть отмечены как упакованные или нет:
Обратите внимание, что у некоторых компонентов 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 дерево. Вместе с этим изменением, некоторые вещи получат галочку в конце:
Попробуйте отредактировать то, что возвращается в обоих случаях, и посмотрите, как изменится результат!
Обратите внимание, как вы создаёте разветвлённую логику с помощью операторов JavaScript if
и return
. В React управление потоком выполнения (например, условия) обрабатывает JavaScript.
Условно возвращаем ничего, с помощью null
В некоторых ситуациях вы вообще не захотите ничего рендерить. Например, вы не хотите показывать упакованные предметы. Компонент должен что-то возвращать. В этом случае вы можете вернуть null
:
if (isPacked) { return null; } return <li className="item">{name}</li>;
Если isPacked
равен true, то компонент не вернёт ничего, null
. В противном случае, он вернёт JSX для рендеринга.
На практике возврат 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 в каждом из случаев:
Этот стиль хорошо работает для простых условий, но используйте его в меру. Если ваши компоненты становятся запутанными из-за слишком большого количества вложенной условной разметки, подумайте об выделении дочерних компонентов, чтобы навести порядок. В React разметка является частью кода, поэтому вы можете использовать такие инструменты, как переменные и функции, чтобы привести в порядок сложные выражения.
Логический оператор И(&&
)
Еще одно часто встречающееся сокращение JavaScript логический оператор И (&&
). Внутри React-компонентов он часто используется, когда вам нужно отрендерить JSX, когда условие true, или не рендерить ничего. С помощью &&
вы можете условно рендерить галочку, если isPacked
равно true
:
return ( <li className="item"> {name} {isPacked && '✔'} </li> );
Вы можете читать это как “если isPacked
, тогда (&&
) рендерим галочку, в противном случае — ничего не рендерим”.
Вот это в действии:
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>
Этот стиль самый многословный, но и самый гибкий. Вот он в действии:
Как и раньше, это работает не только для текста, но и для произвольного JSX:
Если вы не знакомы с 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
.