無料
ご
相
談
・
お
見
積
も
り
2024.10.08
今回はReactで読みやすいコードって何なのかについて考えてみました。
※Reactだけでなく、CSSにも触れています。
一番コードが汚くなってしまうif文について自分なりのベストプラクティスを挙げていきます。
これはよく使われていることが多いのではないでしょうか。
下記のようなコードでデータが存在してかつそのデータの中のコンテンツが存在した場合のようにif文を毎回読んでいくのは疲れますよね。
if("データがあれば"){
if("データの中のcontentが存在すれば"){
特定のデータを更新する
}
else if("データの中のcontentが存在しなければ"){
エラー処理をする
}
}
こんな時に責務の分離をすることでコードが綺麗になります。
if("データがなければ") return エラー処理を返す
if("データの中のcontentが存在しなければ")return エラー処理を返す
特定のデータを更新する
上記のコードのようにエラー処理と正常な処理の分離をすることで責務を分離することでコードの理解速度が向上しますよね。
これはif文のある条件が複数存在する時によく使用されます。
例えば、カテゴリーが10個ぐらい存在していた際にカテゴリーごとに処理内容を変えたいときにif文で長々と書いていると処理が直感的ではなく読みにくいです。
下記のようなコードです。
if("カテゴリーがパソコンであれば"){
データにパソコンのカテゴリーを追加する
}
else if("カテゴリーがスマホであれば"){
データにスマホのカテゴリーを追加する
}
else if("カテゴリーがガラケーであれば"){
データにガラケーのカテゴリーを追加する
}
else if("カテゴリーがデスクトップであれば"){
データにデスクトップのカテゴリーを追加する
}
このコードだとガラケーの時はどんな処理をするのかな〜?と思って探しに行ってもすぐにわかんないし面倒くさいですよね?
改行もすごくわかりにくいですね。
そこでSwitch文の登場です。
switch (カテゴリー) {
case "パソコン":
データにパソコンのカテゴリーを追加する;
break;
case "スマホ":
データにスマホのカテゴリーを追加する;
break;
case "ガラケー":
データにガラケーのカテゴリーを追加する;
break;
case "デスクトップ":
データにデスクトップのカテゴリーを追加する;
break;
default:
// 上記のどれでもない場合の処理
データに何も追加しない;
break;
}
かなりわかりやすくないですか?
ガラケーの処理見ようとするとすぐに見つけれますね。
まずは、何でもかんでもファイルを増やさないことです。
例えば、BlogページでCardコンポーネントを作るときにファイルを別で切り出してしまうことがよくあるかと思います。
僕は、将来に再利用可能性が低い且つ長すぎなければ(30行未満)場合は同じファイルに留めておいてと思っちゃうタイプです。
なぜかというとファイルだけを見たときに直感的にコンポーネントの存在を理解できるからです。
これは結構大事で何でもかんでもroot直下のcomponentに突っ込んでしまうと再利用できるものまで自作することになるからです。
例えば、Cardコンポーネント作成する際にcomponentフォルダを見にいきますが、「Cardsコンポーネント」があったり「CardWithTilteコンポーネント」があったりで何が再利用可能で変更に強いコードなのかがわからなくなり自作することになります。
先ほどの問題にならないためには、root直下のcomponentには「再利用を考えられたコンポーネント」のみを配置するのがベストだと思っています。
プロジェクト全体で使うButton,Card,Titleなどはそこに配置し引数はオプショナルなどで汎用的にするのではなく厳格に指定することで予期せぬバグを未然に防ぎつつ意味のない不安を払拭するのが良いのではないかと思います。
意味のない不安というのは、ButtonコンポーネントをブログページのCardコンポーネントで使ってもデザイン崩れないかな?やButtonを関数ではなくLinkとして使いたいんだけ動くのかな?といったことです。
事前に想定されたコンポーネントにデザインしましょう。
これも先ほどの壊れにくいコンポーネントを作成することの延長なのですが、何となく「string」や「number」を再利用前提のコンポーネントに付与していませんか?
これだと壊れやすいです。
僕は最初は使いにくいぐらいが良いと思っています。
例えば下記のようなタイトルと特徴番号がセットになったコンポーネントの場合、
type Props = {
featureNumber: string
title: string
}
const FeatureTitle:FC<Props> () => {}
これだと甘いかなと思っていて命名でfeatureNumberが番号が入るのかな?と予想できます。
しかし、開発者の私は「"01"」や「"02"」のような文字列を想定していましたが他の開発者は恐らく1や2を入れそうですよね?
こんな事故を防ぐために下記のようなコードにするべくだと思っています。
type Props = {
featureNumber:`${"0" | ""}${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`;
title: string
}
const FeatureTitle:FC<Props> () => {}
これが良いと考えています。
少しの迷いも開発者に与えてはいけないし、壊れにくいプロジェクトにすることで開発者も心地よく開発できます。
これはAPI経由で取得したデータを子コンポーネントに渡す際に独自で型をつけずにAPIの型を再利用することで変更に強くするものです。
下記のようにBlogという型がプロジェクトに作成されていると思うのでBlogの中のcontentを取得することで、contentの中の型が変更された時に柔軟に変更されるし、その変更が起こった際に型エラーが発生すると事前にバグを解消できるということです。
type Props = {
blogContent: Blog["content"]
}
const BlogCard:FC<Props> () => {}
ReactでCSSを使うと昔に比べると遥かに楽になりCSS設計など勉強しなくても良いと思っていました。
しかし、壊れにくい・わかりやすいコードという面ではCSS設計の存在意義はかなり重要だと思います。
具体的に、下記のコードです。
<div className='w-full px-4 mt-4 font-bold text-xl text-gray-700 md:mx-auto md:px-0 md:w-9/12 md:max-w-6xl md:mt-8 text-base leading-relaxed md:text-lg'>
<h1>John Doe</h1>
<p>
Full Stack Developer with a passion for creating interactive web applications.
Loves working with JavaScript and React.
</p>
</div>
divが持つべき責務がバラバラです。
本来であれば、レイアウトを担当して欲しいのに子要素のフォントまで責任を持ってしまっています。
これでは、中の子要素に黒色で小さめのフォントサイズのテキストを追加したくてもグレー色で大きいフォントのテキストが作成されます。
どうすれば良いかというと下記のようなコードだと思ってます。
<div className='w-full px-4 mt-4 md:mx-auto md:px-0 md:w-9/12 md:max-w-6xl md:mt-8'>
<h1 className="font-bold text-xl">John Doe</h1>
<p className="text-gray-700">
Full Stack Developer with a passion for creating interactive web applications.
Loves working with JavaScript and React.
</p>
</div>
これで変更に強いCSSになったと思います。
こんな感じでCSS設計の学習はフロントエンドエンジニアはまだまだ必要だと思ってるのでご興味あれば勉強してみてください。