Особенности условного рендеринга в React

Ревьюю студентов на курсах и часто натыкаюсь на общую проблему с условным рендерингом. Рассказываю.

Вот пишут такой реакт-компонент (для простоты убрал лишнее)

const List: FC<{ id: number }> = ({ id }) => (
  <ul>
    <li><a href="/">домой</a></li>

    {id && (
      <li><a href="/somewhere">куда-то</a></li>
    )}
  </ul>
);

Что здесь: передаем пропом число id, и если оно есть, то рендерим элемент списка.

Вроде бы все хорошо, но на самом деле опасно. Если id будет равен нулю, то компонент не отрендерится. Зато отрендерится 0.

То есть при id === 0 на странице получится такая разметка

<ul>
  <li><a href="/">домой</a></li>
  0
</ul>

Почему так

Первый момент, что если при логическом операторе И (&&) один из операторов ложен, то он и вернется. То есть в нашем случае вернулся 0, т.к. число ноль при логическом преобразовании ложно.

0 && 1 // 0
2 && 3 // 3
1 && 0 && 2 // 0

Второй момент, что в реакте рендерятся числа. То есть вы можете сделать компонент, который возвращает число 0 и все нормально отобразится.

https://codesandbox.io/s/tender-colden-wfgtz?file=/src/App.jshttps://codesandbox.io/s/tender-colden-wfgtz?file=/src/App.js

Другое дело, если бы вернулся не 0, а false — его реакт не отрендерит.

https://codesandbox.io/s/sad-babbage-04ir9?file=/src/App.jshttps://codesandbox.io/s/sad-babbage-04ir9?file=/src/App.js

Поэтому если хоть один логический оператор не булево значение, то я всегда оборачиваю аргументы в Boolean.

То есть в нашем случае лучше будет

const List: FC<{ id: number }> = ({ id }) => (
  <ul>
    <li><a href="/">домой</a></li>

    {Boolean(id) && (
      <li><a href="/somewhere">куда-то</a></li>
    )}
  </ul>
);

Доп. материалы на почитать: