Условный рендеринг¶
Ваши компоненты часто должны отображать разные вещи в зависимости от различных условий. В 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