React Hook Form のサンプルを見ていたら、こんなコードがありました。
というか、React 本家のチュートリアルにもありますね。 https://ja.react.dev/learn/conditional-rendering#logical-and-operator-
{errors.exampleRequired && <span>This field is required</span>}
普段 JavaScript を書かない立場としては、すぐには理解できませんでした。 入力チェックの結果、エラーがある場合ならこういう挙動のはず。
errors.exampleRequired
に何らかのオブジェクトが入っているtrue
と評価されるtrue
と評価されれば、true
が返されるfalse
と評価されれば、false
が返される入力チェックの結果、エラーがない場合ならこうなるよね?
errors.exampleRequired
が undefined
false
と評価されるfalse
が返されるどちらにせよ、true
/false
のいずれかが返されるので <span>This field is required</span>
は出力されないように思えます。
正しく動作させるなら、普通に考えればこうなるかなと。
{errors.exampleRequired ? <span>This field is required</span> : ''}
JavaScript の &&
演算子が Java などと比べて特殊なので、確認してみます。
JavaScript も C 言語の流れを汲んでいる(基本的な文法の面では)ので、基本的には同じです。
const t1 = true;
const t2 = true;
const f1 = false;
const f2 = false;
t1 && t2 // true
t1 && f2 // false
f1 && t1 // false, f1 を評価した時点で全体の結果が確定するので t1 は評価されない
MDN を見ると、以下のような説明があります。
一般的には、この演算子は左から右に向けて評価した際に最初の偽値のオペランドに遭遇したときにはその値を、またはすべてが真値であった場合は最後のオペランドの値を返します。
つまり、論理演算子なので常に true
/false
の真偽値を返すと思いがちですが、実際には以下のような挙動となっています。
false
として扱われる値の場合: 左オペランドを返すtrue
として扱われる値の場合: 右オペランドを返す上記の挙動に当てはめた結果、真偽値型の場合は我々のよく知る挙動となっているわけですね。
ということで、真偽値型以外に適用するとこんなことが起こってしまうわけです。 直感に反しますよね。
const tanaka = '田中まさひろ';
const satoda = '里田まい';
tanaka && satoda // '里田まい'
{errors.exampleRequired && <span>This field is required</span>}
以下の挙動となります。
errors.exampleRequired
に何らかのオブジェクトが入っているtrue
と評価されるerrors.exampleRequired
は undefined
false
と評価されるundefined
なので React は何も出力しないJava などの、型を厳密に扱う言語に慣れていると JavaScript の &&
の挙動は不思議に思えますね。
ですが、ドキュメントをしっかり読めば説明はあるので、注意して少しずつ慣れていきましょう。