Условный рендеринг¶
Ваши компоненты часто должны отображать разные вещи в зависимости от различных условий. В React вы можете условно выводить JSX, используя синтаксис JavaScript, такой как операторы if
, &&
и ? :
.
Вы узнаете
- Как возвращать различные JSX в зависимости от условия
- Как условно включить или исключить фрагмент JSX
- Общие сокращения условного синтаксиса, которые вы можете встретить в кодовых базах React
Условное возвращение JSX¶
Допустим, у вас есть компонент PackingList
, отображающий несколько Item
, которые могут быть помечены как упакованные или нет:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Обратите внимание, что у некоторых компонентов Item
свойство isPacked
установлено в true
вместо false
. Вы хотите добавить галочку (✔) к упакованным элементам, если isPacked={true}
.
Вы можете написать это в виде if/else
оператора, например, так:
1 2 3 4 |
|
Если параметр isPacked
имеет значение true
, этот код возвращает другое JSX-дерево. С этим изменением некоторые элементы получают галочку в конце:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Попробуйте изменить то, что будет возвращено в любом случае, и посмотрите, как изменится результат!
Обратите внимание, как вы создаете разветвленную логику с помощью операторов JavaScript if
и return
. В React поток управления (как и условия) обрабатывается JavaScript.
Условное возвращение ничего с null
¶
В некоторых ситуациях вы вообще не захотите ничего выводить. Например, вы не хотите показывать упакованные элементы вообще. Компонент должен что-то возвращать. В этом случае вы можете вернуть null
:
1 2 3 4 |
|
Если isPacked
истинно, компонент не вернет ничего, null
. В противном случае он вернет JSX для рендеринга.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
На практике возврат null
из компонента не является обычным делом, поскольку это может удивить разработчика, пытающегося его отобразить. Чаще всего вы условно включаете или исключаете компонент в JSX родительского компонента. Вот как это сделать!
Условное включение JSX¶
В предыдущем примере вы контролировали, какое (если вообще!) дерево JSX будет возвращено компонентом. Возможно, вы уже заметили дублирование в выводе рендера:
1 |
|
очень похожа на
1 |
|
Обе условные ветви возвращают <li className="item">...</li>
:
1 2 3 4 |
|
Хотя такое дублирование не вредно, оно может усложнить сопровождение вашего кода. Что если вы захотите изменить className
? Вам придется делать это в двух местах в вашем коде! В такой ситуации вы можете условно включить немного JSX, чтобы сделать ваш код более DRY.
Условный (тернарный) оператор (? :
)¶
В JavaScript есть компактный синтаксис для записи условного выражения — условный оператор или "тернарный оператор".
Вместо этого:
1 2 3 4 |
|
Вы можете написать это:
1 2 3 4 5 |
|
Вы можете прочитать это как "если isPacked
истинно, то (?
) render name + ' ✔'
, иначе (:
) render name
".
Являются ли эти два примера полностью эквивалентными?
Если вы знакомы с объектно-ориентированным программированием, вы можете предположить, что два приведенных выше примера мало чем отличаются друг от друга, поскольку один из них может создавать два разных "экземпляра" <li>
. Но элементы JSX не являются "экземплярами", потому что они не хранят никакого внутреннего состояния и не являются реальными узлами DOM. Это легкие описания, как чертежи. Так что эти два примера, на самом деле, полностью эквивалентны. В сохранение и сброс состояния подробно описано, как это работает.
Теперь предположим, что вы хотите обернуть текст завершенного элемента в другой HTML-тег, например <del>
, чтобы вычеркнуть его. Вы можете добавить еще больше новых строк и круглых скобок, чтобы было легче вложить больше JSX в каждом из случаев:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Этот стиль хорошо работает для простых условий, но используйте его умеренно. Если в ваших компонентах слишком много вложенной условной разметки, подумайте об извлечении дочерних компонентов, чтобы навести порядок. В React разметка является частью вашего кода, поэтому вы можете использовать такие инструменты, как переменные и функции, чтобы привести в порядок сложные выражения.
Логический оператор AND (&&
)¶
Еще одно часто встречающееся сокращение — это оператор JavaScript logical AND (&&
). В компонентах React это часто возникает, когда вы хотите отобразить некоторый JSX, когда условие истинно, или ничего не отображать в противном случае. Используя &&
, вы можете условно отобразить флажок только если isPacked
является true
:
1 2 3 4 5 |
|
Вы можете прочитать это как "если isPacked
, то (&&&
) выводим галочку, иначе ничего не выводим ".
Вот это в действии:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Выражение JavaScript && expression возвращает значение своей правой части (в нашем случае, галочку), если левая часть (наше условие) истина
. Но если условие false
, то все выражение становится false
. React рассматривает false
как "дыру" в дереве JSX, так же как null
или undefined
, и ничего не отображает на его месте.
Внимание
Не ставьте числа в левой части &&
.
Чтобы проверить условие, JavaScript автоматически преобразует левую часть в булево значение. Однако если левая часть равна 0
, то все выражение получает это значение (0
), и React с радостью отобразит 0
, а не ничего.
Например, распространенной ошибкой является написание кода типа messageCount && <p>Новые сообщения</p>
. Легко предположить, что он ничего не отображает, когда messageCount
равно 0
, но на самом деле он отображает сам 0
!
Чтобы исправить это, сделайте левую часть булевой: messageCount > 0 && <p>Новые сообщения</p>
.
Условное присвоение JSX переменной¶
Когда ярлыки мешают писать простой код, попробуйте использовать оператор if
и переменную. Вы можете переназначать переменные, определенные с помощью let
, поэтому начните с указания содержимого по умолчанию, которое вы хотите отобразить, — имени:
1 |
|
Используйте оператор if
для переназначения выражения JSX в itemContent
, если isPacked
равно true
:
1 2 3 |
|
фигурные скобки открывают "окно в JavaScript". Вставьте переменную с фигурными скобками в возвращаемое дерево JSX, вложив ранее вычисленное выражение внутрь JSX:
1 |
|
Этот стиль самый многословный, но и самый гибкий. Вот он в действии:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Как и раньше, это работает не только для текста, но и для произвольного JSX:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Если вы не знакомы с JavaScript, такое разнообразие стилей может поначалу показаться ошеломляющим. Однако их изучение поможет вам читать и писать любой код JavaScript — и не только компоненты React! Выберите для начала тот, который вам больше нравится, а затем снова обратитесь к этому справочнику, если вы забудете, как работают другие.
Итоги
- В React вы управляете логикой ветвления с помощью JavaScript.
- Вы можете вернуть выражение JSX условно с помощью оператора
if
. - Вы можете условно сохранить некоторые JSX в переменную, а затем включить их в другие JSX с помощью фигурных скобок.
- В JSX,
{cond ? <A /> : <B />}
означает “ifcond
, render<A />
, otherwise<B />
”. - В JSX,
{cond && <A />}
означает “ifcond
, render<A />
, otherwise nothing”. - Эти сокращения являются общепринятыми, но вы можете не использовать их, если предпочитаете простое
if
.
Задачи¶
1. Показать значок для незавершенных элементов с ? :
¶
Используйте условный оператор (cond ? a : b
) для отображения ❌, если isPacked
не является true
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Показать решение
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
2. Показать важность элемента с помощью &&
¶
В этом примере каждый Item
получает числовой параметр importance
. Используйте оператор &&
, чтобы отобразить "(Важность: X)" курсивом, но только для тех элементов, которые имеют ненулевую важность. В итоге ваш список предметов должен выглядеть следующим образом:
- Космический скафандр (Важность: 9).
- Шлем с золотым листом
- Фотография Тама (Важность: 6)
Не забудьте добавить пробел между двумя метками!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Показать решение
Это должно помочь:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Обратите внимание, что вы должны написать importance > 0 && ...
, а не importance && ...
, чтобы если importance
равно 0
, 0
не отображалось как результат!
В этом решении используются два отдельных условия для вставки пробела между именем и меткой важности. В качестве альтернативы можно использовать фрагмент с пробелом: importance > 0 && <> <i>...</i>
или добавьте пробел непосредственно внутри <i>
: importance > 0 && <i> ...</i>
.
3. Рефакторинг серии ? :
на if
и переменные¶
Этот компонент Drink
использует серию ? :
условий для отображения различной информации в зависимости от того, является ли name
пропс "чай"
или "кофе"
. Проблема в том, что информация о каждом напитке распределена по нескольким условиям. Переработайте этот код, чтобы использовать один оператор if
вместо трех ? :
условий.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
После рефакторинга кода для использования if
, есть ли у вас дальнейшие идеи, как его упростить?
Показать решение
Вы можете пойти разными путями, но вот одна из отправных точек:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
Здесь информация о каждом напитке сгруппирована вместе, а не распределена по нескольким условиям. Это облегчает добавление новых напитков в будущем.
Другим решением может быть полное удаление условий путем перемещения информации в объекты:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Источник — https://react.dev/learn/conditional-rendering