Тернарные операторы и логическое “И” в React.js
Всем привет! Вы читаете перевод статьи Donavon West «Conditional Rendering in React using Ternaries and Logical AND»
Существуют несколько способов заставить React рендерить то, что вам нужно. Вы можете использовать традиционный оператор if или switch. В этой статье мы рассмотрим этим способам альтернативу. Будьте осторожны: она несет некоторые сюрпризами, с которыми стоит быть поаккуратнее.
Тернарные операторы vs if/else
Давайте представим, что наш компонент получает свойство name. Если строка не пустая, то мы выведем приветствие, а иначе мы предложим пользователю зарегистрироваться.
Это можно сделать с помощью компонента-функции без состояний (ориг. SFC — Stateless Function Component):
const MyComponent = ({ name }) => {
if (name) {
return (
Привет, {name}
);
}
return (
Пожалуйста, войдите в ваш аккаунт
);
};
Здесь все довольно понятно. Но мы можем лучше! Вот тот же пример, написанный с тернарными операторами:
const MyComponent = ({ name }) => (
{name ? `Привет, ${name}` : 'Пожалуйста, войдите в ваш аккаунт'}
);
Обратите внимание, как сократился наш код. Поскольку мы используем стрелочную функцию, нам не нужен return, а тернарный оператор позволяет избавиться от повторения html-тегов.
Тернарные операторы vs логическое «И»
Как видите, тернарные операторы удобны в условиях if/else. Но что, если у нас только if?
Приведем другой пример. Теперь если isPro у нас true, мы выводим надпись (на картинке после — кубок). Также мы выводим количество звезд, если их больше 0. Можно сделать так:
const MyComponent = ({ name, isPro, stars}) => (
Hello {name}
{isPro ? 'Проооофи' : null}
{stars ? (
Stars:{'* '.repeat(stars)}
) : null}
);
Заметьте, что else возвращает null. Поскольку тернарный оператор ожидает else, то этого не избежать.
Для одного лишь if существует нечто более приятное, логическое «И»:
const MyComponent = ({ name, isPro, stars}) => (
Hello {name}
{isPro && 'Проооофи'}
{stars && (
Stars:{'* '.repeat(stars)}
)}
);
Не сильно-то отличается, однако теперь у нас нет надоедливого : null (то есть условия else). Все, по идее, должно отрендериться как и раньше.
Что это? Что произошло с Джоном? Вместо пустоты у нас откуда-то взялся 0. Вот это и есть сюрприз, о котором говорилось раньше.
Если обратиться к MDN, то логическое «И» (&&):
expr1 && expr2
Возвращает expr1, если может быть преобразовано в false; иначе возвращает expr2. Причем, при использовании с логическими значениями (boolean), && вернет true, если оба значения true; иначе вернет false.
Ну ладно. Прежде чем вы пойдете глотать антидепрессанты, позвольте объяснить.
В нашем случае, expr1 — это stars, у которого значение 0. Поскольку ноль — ложь, то и возвращает изначальное состояние. Видите, не так уж и сложно.
Можно переписать по-человечески:
Если expr1 ложно, то вернет expr1; иначе вернет expr2.
Поэтому, когда используете логическое «И» с небулевым значением, то нужно что-то сделать с ложью, чтобы React это не рендерил.
Рассмотрим несколько решений:
{!!stars && (
{'* '.repeat(stars)}
)}
Заметьте знак ! перед stars — он означает двойное отрицание. То есть, если stars — 0, то ! stars уже false. А именно это нам и нужно.
Если вам не особо по душе двойное отрицание, то вот еще пример:
{Boolean(stars) && (
Функция Boolean () банально преобразует переменную в true или false.
Можно сравнить значение переменной с 0 — результат тот же:
{stars > 0 && (
Кстати, пустые строки ждет участь чисел. Но поскольку отрендерится пустая строка как », то вы ее и не заметите. Если же вы перфекционист, можете обработать строки как числа в примерах выше.
Другое решение
Когда вы увеличите ваше веб-приложение, будет удобно разделить переменные и создать одну shouldRenderStars с условием. Тогда вы сразу будете работать с логическими значениями в логическом «И»:
const shouldRenderStars = stars > 0;
return (
{shouldRenderStars && (
{'* '.repeat(stars)}
)}
);
В будущем, когда бизнес потребует проверять, скажем, на авторизацию, наличие собаки, предпочтения в пиве, нужно будет просто немного изменить shouldRenderStars, а то, что будет возвращено, не менять:
const shouldRenderStars =
stars > 0 && loggedIn && pet === 'dog' && beerPref === 'light`;
return (
{shouldRenderStars && (
{'* '.repeat(stars)}
)}
);
Заключение
Я один из тех, кто считает, что нужно пользоваться всеми функциями вашего языка программирование. Для JavaScript это означает использование по назначению тернарных операторов, условий if/else и логических «И» для простой замены if.
Надеюсь, вам была полезна эта статья. И обязательно напишите: как вы используете описанное выше? Спасибо за внимание.