記事を書いたきっかけ
ReactやNext.jsで特定の値がtrueの時はこのTSXを表示したいってパターンよくあると思います
こんな感じ
const App = () => {
const food = 'カレーライス';
return (
<div>
{food === 'カレーライス' && <p>今夜はCoCo壱にしよう</p>}
</div>
);
};
しかしこれが以下のように変わると
const App = () => {
const spicyLevel = 0;
return (
<div>
{spicyLevel && <p>{spicyLevel}辛にしよう</p>}
</div>
);
};
あれ?「0辛にしよう」が表示されない?
0って変数に入ってる値だな?と
なぜこうなるのか説明できなかったので備忘録として記事に残します
&&演算子ってなに?
&& は論理演算子の「AND」
新人の時によく言われたのが「両方が true のときに true」 を返す
でも JavaScript(TypeScript)だと単純に true / falseを返す(bool値を返す)だけではない
以下公式ドキュメントからの引用
論理積 (&&) はオペランドを左から右に向けて評価し、遭遇した最初の偽値のオペランドを直ちに返します。すべての値が真値であった場合、最後のオペランドの値が返されます。
一般的には、この演算子は左から右に向けて評価した際に最初の偽値のオペランドに遭遇したときにはその値を、またはすべてが真値であった場合は最後のオペランドの値を返します。
オペランドって?
「演算子の左右に書かれる値」のこと
この場合 "カレー"
と "ラーメン"
がオペランド、&&
が演算子です。
const result = "カレー" && "ラーメン";
もっと噛み砕いてみる
具体的な動き
- 左から右に評価する
- まずオペランドを truthy / falsy として判定する
- falsy を見つけたら、そのオペランドの元の値を返す
- すべて truthy だったら、最後のオペランドの元の値を返す
truthy / falsyとは?
JavaScript では if (...) や && のような条件式に、bool値以外を書いても判定できる
数値や文字列など、いろんな値が自動的に「true っぽい」か「falseっぽい」かに変換され、このときtrueとみなされる値をtruthy、falseとみなされる値をfalsyと呼びます。
truthy
JavaScript において、真値 (truthy) は論理値のコンテキストに現れた時に true とみなされる値のことです。偽値 (falsy) として定義された値 (つまり、false, 0, -0, 0n, "", null, undefined, NaN) を除くすべての値は真値です。
falsy
偽値 (falsy または falsy) な値とは、論理型コンテキストに現れたときに偽とみなされる値です。
JavaScript は条件文や繰り返しなどの場面で、任意の値を強制的に論理型に型変換します。
falsyな値
値 | 型 |
---|---|
false |
boolean |
0 (数字) |
number |
-0 (数字) |
number |
0n |
bigint |
"" (空文字) |
string |
null |
null |
undefined |
undefined |
NaN (Not a Number) |
number |
上記の図で表記されていない値はtruthy
です!
言語によってtruthyな値とfalsyな値は変わる
表示がバグっていた原因
結論、数値の 0
が falsy だから
Reactはnull
は描画しませんが、0
は値として描画してしまう
以下公式ドキュメントからの引用
null を使って何も返さないようにする
場合によっては、何もレンダーしたくないことがあります。例えば、梱包済みの荷物は一切表示したくない、という場合です。コンポーネントは常に何かを返す必要があります。このような場合、null を返すことができます。
具体的な処理の流れ
const App = () => {
const spicyLevel = 0;
return (
<div>
{spicyLevel && <p>{spicyLevel}辛にしよう</p>}
</div>
);
};
-
spicyLevel
に代入されてる0
を直接判定していた - 数値の
0
はfalsy
な値 -
falsy
を見つけたら、そのオペランドの元の値を返すので -
spicyLevel
に代入されてる0
がそのまま表示される
対策
対策1:明示的に真偽値を比較する
左辺にbool値を入れる
{spicyLevel > 0 && <p>辛いの苦手だから0辛にしよう</p>}
対策2:三項演算子で出し分ける
const App = () => {
const spicyLevel = 0;
return (
<div>
{spicyLevel ? <p>{spicyLevel}辛にしよう</p> : <p>今日は甘口で!</p>}
</div>
);
};
まとめ
Reactの公式ドキュメントに以下の記載がありました
&&の左辺に数値を置かない
JavaScript は条件をテストする際、左の辺を自動的に真偽値に変換します。しかし、左の辺が 0 の場合は、式全体がその 0 という値に評価されてしまうため、React は何もレンダーしないのではなく 0 を表示します。
三項演算子使っても対処はできますが、ネストが深くなってコードが読みづらくなる可能性があるので、公式に習って対策1の方法で実装するのがベストかなと思います。