💰

React開発で迷わない:一時コンポーネントは$lowerCamelCaseで書こう

に公開

結論

この記事は

  • 一時定義のコンポーネントの命名規則を「$ + lowerCamelCase」にする(新ルール)
  • exportするコンポーネントはUpperCamelCase(従来のルール)

という命名規則を提案するという内容です。

はじめに

こんにちは。
みなさんReactで開発してますか?
私はここ10年くらい、ずっとReactを触り続けてます。
この記事では最近使ってみてよかった命名ルールをみなさんに提案してみたいと思います。

既存の命名ルールのおさらい

Reactコンポーネントの命名の基本は「UpperCamelCase」です。

export const Description = () => {
    return (
        <div>
            コンポーネントの定義をしています
        </div>
    )
}

定義したコンポーネントを使うときはこうですね。

import {Description} from "./Description.tsx"

const App = () => {
    return (
        <Description/>
    )
}

さて、コンポーネントの命名がなぜ「UpperCamelCase」になっているかというと、ネイティブのWeb要素を描画するのか、定義したコンポーネントを呼び出していのかをJSX上で区別するためです。

import {Description} from "./Description.tsx"

const App = () => {
    return (
        <html>
            <title>ページタイトル</title> //ここはhtmlのtitle要素をレンダリング
            <Description/> //ここはDescriptionコンポーネントを呼び出し
        </html>
    )
}

javascript/typescriptにおいて、変数の命名規則は「lowerCamelCase」がスタンダードだと思いますが、JSX上で要素かコンポーネントかを区別するために、コンポーネントを「UpperCamelCase」で命名するというルールになっているわけです。

命名ルールの問題

問題はここからです。
前述の通り、コンポーネント名はUpperCamelCaseで定義しないとそもそもコンポーネントとして認識されないです。(正確には先頭が大文字である必要があります)

このルールは一時的なコンポーネントを作成するときにも適用されます。
これは特にstyled-componentsを使うときにしんどいなと思っていました。

import styled from "styled-components"
import {Description} from "./Description.tsx"

//スタイリングしたh1要素のコンポーネント
const Title = styled.h1`
    color: red;
`

//lowerCamelCaseは使えない
const box = styled.div`
    padding: 8px;
`

const App = () => {
    return (
        <box> //これはコンポーネントとして解釈されず、<box>という要素がそのまま描画されてしまう
            <Title>タイトル</Title> //コンポーネントとして解釈されるので正しく描画される
            <Description/> //外部定義のコンポーネントよびだし
        </box>
    )
}

ちょっとコード例を出してみました。
ここでしんどいなと思うのが、Appコンポーネントのレンダリング内容の可読性です。

Appのreturnを見ると、TitleとDescriptionは完全に同列のコンポーネントに見えます。
でも、レビュワーからすると重要度は違うんですよね。

Titleコンポーネントの「重要度」は低いです。
このファイルでのみ定義しているコンポーネントですし、やってることはスタイルの適用だけなのでロジックが入り込む余地もありません。

対してDescriptionコンポーネントの「重要度」は高めです。
正しくpropsは渡せているのか、内部のロジックはここで利用するコンポーネントとして妥当か。
こういった整合性を気にする必要があるからです。

個人的な感覚でいえば一時的なコンポーネント(上記のTitleのようなもの)を「lowerCamelCase」で定義できるのが一番良さそうですが…
前述の通りlowerCamelCaseで変数を定義してしまうとJSX上ではコンポーネントとして解釈されなくなってしまいます。

$を頭につけよう

ここで登場するのが「$」記号です。
じつは先頭に$をつけた場合もJSX上でコンポーネントとして解釈されます。

import styled from "styled-components"
import {Description} from "./Description.tsx"

//スタイリングしたh1要素のコンポーネント
const $title = styled.h1`
    color: red;
`

//$をつければlowerCamelCaseが使える
const $box = styled.div`
    padding: 8px;
`

const App = () => {
    return (
        <$box> //これはコンポーネント呼び出し
            <$title>タイトル</$title> //このファイルのどこかで定義してある一時的なコンポーネント
            <Description/> //外部定義コンポーネント
        </$box>
    )
}

先ほどの例を「$ + lowerCamelCase」で書き直してみました。
どうでしょうか?先ほどは同列だったTitleとDescriptionですが、この規則だと明確に重要度を分けて表現することができると思います。

個人的に気に入っているのが以下の点ですね。

  • lowerCamelCaseで「ローカルスコープ感」を出せる
  • $をプレフィックスとして書くだけなので書き方を覚えやすい
  • styled-componentsに限らず外部に「公開しない」コンポーネントの定義全般に利用できる
  • $記号には演算子としての機能が言語的にアサインされていないので混乱しづらい

おわりに

ということで、$ + lowerCamelCaseでの命名を提案させてもらいました。
ものすごく地味なルールですが、かなり可読性高くなるなと感じています。
$という記号自体に馴染みがない開発者もいるかもしれませんが…

とくにemotionのstyledやstyled-componentsを活用している場合は、劇的に可読性が上がると思うのでぜひ試してみてほしいです。
感想ももらえるとうれしいですね。

※ちなみに他の記号としては「_」アンダーバーも利用することはできますが、privateなクラス変数を表す言語があるので「意味が強すぎる」上に、アンダーバーは「未使用変数」を表すプレフィックスでもあるので微妙だなという判断です。

Discussion