Тернарные операторы и логическое “И” в React.js

Тернарные операторы и логическое “И” в React.js

Nuances of programming

Перевод статьи Donavon West: "Conditional Rendering in React using Ternaries and Logical AND"

Тернарные операторы 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). Все, по идее, должно отрендериться как и раньше.

Что это? Что произошло с Джоном? Вместо пустоты у нас откуда-то взялся 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 нуждается в переводчиках.
Подробности вы можете узнать написав администратору канала через бота или на почту :)


Источник

Report Page