Тернарные операторы и логическое “И” в React.js
Nuances of programmingПеревод статьи Donavon West: "Conditional Rendering in React using Ternaries and Logical AND"
![](/file/565e1ee52703f33928c9c.png)
Тернарные операторы vs if/else
Давайте представим, что наш компонент получает свойство name. Если строка не пустая, то мы выведем приветствие, а иначе мы предложим пользователю зарегистрироваться.
Это можно сделать с помощью компонента-функции без состояний (ориг. SFC — Stateless Function Component):
const MyComponent = ({ name }) => { if (name) { return ( <div className="hello"> Привет, {name} </div> ); } return ( <div className="hello"> Пожалуйста, войдите в ваш аккаунт </div> ); };
Здесь все довольно понятно. Но мы можем лучше! Вот тот же пример, написанный с тернарными операторами:
const MyComponent = ({ name }) => ( <div className="hello"> {name ? `Привет, ${name}` : 'Пожалуйста, войдите в ваш аккаунт'} </div> );
Обратите внимание, как сократился наш код. Поскольку мы используем стрелочную функцию, нам не нужен return, а тернарный оператор позволяет избавиться от повторения html-тегов.
Тернарные операторы vs логическое “И”
Как видите, тернарные операторы удобны в условиях if/else. Но что, если у нас только if?
Приведем другой пример. Теперь если isPro у нас true, мы выводим надпись (на картинке после — кубок). Также мы выводим количество звезд, если их больше 0. Можно сделать так:
const MyComponent = ({ name, isPro, stars}) => ( <div className="hello"> <div> Hello {name} {isPro ? 'Проооофи' : null} </div> {stars ? ( <div> Stars:{'* '.repeat(stars)} </div> ) : null} </div> );
Заметьте, что else возвращает null. Поскольку тернарный оператор ожидает else, то этого не избежать.
Для одного лишь if существует нечто более приятное, логическое “И”:
const MyComponent = ({ name, isPro, stars}) => ( <div className="hello"> <div> Hello {name} {isPro && 'Проооофи'} </div> {stars && ( <div> Stars:{'* '.repeat(stars)} </div> )} </div> );
Не сильно-то отличается, однако теперь у нас нет надоедливого : null (то есть условия else). Все, по идее, должно отрендериться как и раньше.
![](https://habrastorage.org/webt/9y/zp/br/9yzpbrxiggesj7-c3xkjpvazy2g.png)
Что это? Что произошло с Джоном? Вместо пустоты у нас откуда-то взялся 0. Вот это и есть сюрприз, о котором говорилось раньше.
Если обратиться к MDN, то логическое “И” (&&):
expr1 && expr2
Возвращает expr1, если может быть преобразовано в false; иначе возвращает expr2. Причем, при использовании с логическими значениями (boolean), && вернет true, если оба значения true; иначе вернет false.
Ну ладно. Прежде чем вы пойдете глотать антидепрессанты, позвольте объяснить.
В нашем случае, expr1 — это stars, у которого значение 0. Поскольку ноль — ложь, то и возвращает изначальное состояние. Видите, не так уж и сложно.
Можно переписать по-человечески:
Если expr1 ложно, то вернет expr1; иначе вернет expr2.
Поэтому, когда используете логическое “И” с небулевым значением, то нужно что-то сделать с ложью, чтобы React это не рендерил.
Рассмотрим несколько решений:
{!!stars && ( <div> {'* '.repeat(stars)} </div> )}
Заметьте знак !! перед stars — он означает двойное отрицание. То есть, если stars — 0, то !!stars уже false. А именно это нам и нужно.
Если вам не особо по душе двойное отрицание, то вот еще пример:
{Boolean(stars) && (
Функция Boolean() банально преобразует переменную в true или false.
Можно сравнить значение переменной с 0 — результат тот же:
{stars > 0 && (
Кстати, пустые строки ждет участь чисел. Но поскольку отрендерится пустая строка как ‘’, то вы ее и не заметите. Если же вы перфекционист, можете обработать строки как числа в примерах выше.
Другое решение
Когда вы увеличите ваше веб-приложение, будет удобно разделить переменные и создать одну shouldRenderStars с условием. Тогда вы сразу будете работать с логическими значениями в логическом “И”:
const shouldRenderStars = stars > 0; return ( <div> {shouldRenderStars && ( <div> {'* '.repeat(stars)} </div> )} </div> );
В будущем, когда бизнес потребует проверять, скажем, на авторизацию, наличие собаки, предпочтения в пиве, нужно будет просто немного изменить shouldRenderStars, а то, что будет возвращено, не менять:
const shouldRenderStars = stars > 0 && loggedIn && pet === 'dog' && beerPref === 'light`; return ( <div> {shouldRenderStars && ( <div> {'* '.repeat(stars)} </div> )} </div> );
Заключение
Я один из тех, кто считает, что нужно пользоваться всеми функциями вашего языка программирование. Для JavaScript это означает использование по назначению тернарных операторов, условий if/else и логических “И” для простой замены if.
Надеюсь, вам была полезна эта статья.
Канал Nuances of programming нуждается в переводчиках.
Подробности вы можете узнать написав администратору канала через бота или на почту :)