0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Reactではifやswitchの条件分岐は使えない!!

Posted at

最近、本格的にReactを使い始めました。なぜ、使い始めたかというとWordPressのサイト制作でいよいよ自作のブロックを制作しなければならないなと思ったからです。
しかし、これまでのプログラミングとは随分と違う流儀があることに悩まされます。その中でもifやswithが普通に使えないということを最近になって知りました。じゃあどうやって条件分岐させるのか。
その方法をいくつかマスターしかけているのでブログでアウトプットして自分に定着させるとともに、React初学者の方に向けての情報提供になればと思っています。

Reactの状態変数はlet宣言で書き換えることは非推奨

if文やswitch文を使いたくなるのは、条件によって変数の値を変化させたいというのが、初歩的な動機だと思います。ところがReactでは変数宣言であるletを使うことが非推奨であるといいます。これはなぜかと言われると正直なところしっかりとは理解できていません。ChatGPTに質問すると、こんな答えが返ってきます。

Reactにおいて変数にlet宣言をしてswitch文で条件分岐させることは、推奨されていません。これは、Reactの状態管理の仕組みと相性が悪いためです。
Reactでは、UIの状態を状態変数(state)として管理することが推奨されています。状態変数は、setState()メソッドを使用して更新することができます。setState()メソッドは非同期的に状態を更新するため、同期的に状態を更新するletやvarの代わりに、常にconst宣言を使用することが推奨されています。

なんだかよくわからないのですが、デバッガーでReactコンポーネントをトレースするとソースコードの同じところを何度もとおります。これが非同期処理となんらか関係があるのかなという程度しか理解できていません。どなたか教えていただけると嬉しいです。いずれにしても変数はほとんどがconst宣言してあって直接書き換えられないものと考えなければならないようです。
とにかく、画面にレンダリングされる元となる変数はlet宣言しないようにすべきであることは間違いありません。
それでハマったことは数知れずです。

こんな書き方はないでしょうよ!?

間違っても

if (a===0){
	const b=1;
}else{
	const b=2;
}

などととは書けません。これ自体はエラーにはならないですが、if文の外にはbのスコープは効いていないので、設定した定数bは使うことができません。仕方がないので

let b;
if (a===0){
	b=1;
}else{
	b=2;
}

これでbは使えるようになり、エラーも出ません。しかし、ゆくゆくbの値をレンダリングするような処理を書くようなことになった時に痛い目をみるハメに陥ります。

まずは3項演算子

そこで多用されるのが3項演算子です。

const b = a==0 ? 1 : 0

これなら全く問題ありません。この書き方は決して最近の書き方ではなく古くから使われています。
単純な条件分岐ならこの方法が一番です。

オブジェクトリテラルを使用する

でも、この書き方で多分岐を処理するのは大変です。

const b = a==0 ? 1 : 
          a==1 ? 2 : 
          a==2 ? 3 :
          0

これでもわからなくはないのですが、可読性がよくないとされています。そこで

const messageMap = {
  'condition1': '条件1の場合のメッセージ',
  'condition2': '条件2の場合のメッセージ',
  'condition3': '条件3の場合のメッセージ',
  // 以下同様に続く
};

const message = messageMap[condition];

condition変数によってmessageMapの内容が検索され、状態変数messageに値が返ります。この書き方ならすっきりしますよね。

関数を使用する

ifやswitchが使えないといっても直接変数の値を書き換えるような処理はできないというだけで、それさえしなければ使えます。以下の例では関数内でif文を使っていますが、messageを書き換えるようなことはしていません。関数の戻り値を条件によって変更しているだけです。これによってmessageはconst宣言で初期化されることになり、条件によって変更されることはありません。

function getMessage(condition) {
  if (condition === 'condition1') {
    return '条件1の場合のメッセージ';
  } else if (condition === 'condition2') {
    return '条件2の場合のメッセージ';
  } else if (condition === 'condition3') {
    return '条件3の場合のメッセージ';
  }
  // 以下同様に続く
}

const message = getMessage(condition);

上記の例では条件がconditionの価しかないのですが、複数の条件を処理するときには他の方法より威力を発揮します。具体的には

 const getPadding = (isIcon, icon_style)=>{
      if( !isIcon){
        return 'メッセージ1'
      }
      if(icon_style==="left"){
        return 'メッセージ2'
      }
      if(icon_style.icon==="right"){
        return 'メッセージ3'
      }
}
 const padding_prm = getPadding(isIcon, icon_style);

このようにisIconがtrueでなければ処理を終え、それ以降はicon_styleを使うなどというときは非常に便利です。

論理 && 演算子によるインライン If

これもReact特有の書き方のようです。
でも、使えると使えないとで書けるコードの幅に大きな差をもたらすものと思います。
具体的な書き方は

return(
    {unreadMessages.length > 0 &&
    	<h2>
          You have {unreadMessages.length} unread messages.
        </h2>
    }
)

という感じで、レンダリングしたいコンポーネントを{}で囲んだうえで、{}内の冒頭に「条件式 &&」と入れるのです。
これでreturn文の中でレンダリングの条件を指定できます。
この書き方を知らないと

let addConpornent = null;
if(unreadMessages.length > 0)
	addConponent = <h2>You have {unreadMessages.length} unread messages.</h2>
return addConpornent

なんていうコードを書かざるを得ないという結論になったりしませんか?
試していませんが、このコードはたぶんまともには動かないと思います。

まとめ

私はReactは初学者ですが、レトロなJavascriptやJava、PHPなどの言語をそれなりに経験してきました。しかし、まともに条件分岐さえ書けないなんて経験は初めてです。
条件分岐なんてプログラミング初心者の最初の一歩などとあなどってはいけません。
このようにみるとReactで使用することができる条件分岐のバリエーションは相当数あります。しかし、3項演算子はともかく、その他の手法は教えてもらわないと気が付かないでしょう。
ちなみに、私はChatGPTに教えてもらいました。
ChatGPTには感謝しないといけませんね。
ということで、まとめとさせていただきます。最後まで読んでいただきありがとうございました。

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?