問い
どうしてReact
ではclass
でなくclassName
を使うのか?
結論
class
は JavaScript
の予約語になっているため、やむを得ず className
に改名している。
JSXとは
まず前提知識として、JSXについて少し知っている必要があります。
JSX
とはjsの中にxmlライクな記述ができるようになった拡張構文で、
ブラウザで実行される前に、jsオブジェクトを生成する式に変換します。
例えば、以下のようなJSX
があるとします。
const button = <button type="submit" onClick={() => alert('クリックされました')}>送信</button>;
これは、ブラウザで実行される前に以下のjs
に変換されます。
const button = React.createElement(
"button",
{ type: "submit", onClick: () => alert('クリックされました') },
"送信"
);
つまり、react
におけるJSX
とは、React.createElement
を生成する記法ということになります。
React.createElementは公式にも説明がある通り、React
の要素を生成するReactAPI
なので、JSX
から返却されるオブジェクトによってReact
要素が生成されます。
JSX
ファイルの中でHTML
っぽく書けるのに、実はHTML
のプロパティとは全くの別物だった...!!
話は戻り、どうしてReact
ではclass
でなくclassName
を使うのか?
JSX
はjs
に変換されるので、JSX内でclassを使用するとjsのプロパティとして解釈されます。
しかし、jsには class の予約語が存在しているのでJSXでclassが使用されるのを避けています。
ちなみに同じ理由で改名を余儀なくされているのが for
で、htmlFor
に改名されています。
以下余談
組み込みコンポーネント
Reactのコンポーネントには、以下の2種類が存在します
- ユーザー定義コンポーネント
- 組み込みコンポーネント
公式が公開しているのような組み込みコンポーネント以外に、
DOMコンポーネントもサポートしています。
以下のように一見、標準HTML
タグに見えるdiv
やp
が組み込みコンポーネントに当たります。
const content = <div className="wrapper">Some content</div>
div
にカーソルを当ててみると、それなりのprop
を受け取ることができます。
このpropsの型の在処はinterface IntrinsicElementsに定義されています。
※ ちなみに、Intrinsic
は「〔人・物に〕本来備わっている、固有の、本質的な」
という意味があります。
div
なら以下のように定義されており、
div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
React.HTMLAttributes
は以下のように定義されている。
interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
// React-specific Attributes
defaultChecked?: boolean | undefined;
defaultValue?: string | number | readonly string[] | undefined;
suppressContentEditableWarning?: boolean | undefined;
suppressHydrationWarning?: boolean | undefined;
// Standard HTML Attributes
accessKey?: string | undefined;
autoFocus?: boolean | undefined;
className?: string | undefined;
contentEditable?: Booleanish | "inherit" | "plaintext-only" | undefined;
// ...略
これらがJSX divタグ
が受け取れるprops
に繋がってくるというわけです。
複数の JSX タグを返す時にフラグメントでラップする
周知ですが、以下のようなコンポーネントではエラーが発生しますね。
export function Item() {
return (
<input type="text" placeholder="名前を入力" />
<button type="submit" onClick={() => alert('クリックされました')}>送信</button>
);
}
JSX
は単一のタグを返却するというルールがあるので以下のような修正を加えるはずです。
export function Item() {
return (
<>
<input type="text" placeholder="名前を入力" />
<button type="submit" onClick={() => alert('クリックされました')}>送信</button>
</>
);
}
エラーになるからとりあえず従ったけど、どうしてなのか?
前述した通り、JSX
は HTML
のように見えますが、「最終的にはJavaScript
オブジェクトに変換される」ということが分かっているならこれも理解できます。
公式のコラムに説明がありました。
関数から 2 つのオブジェクトを返したい場合、配列でラップしないといけませんよね。2 つの JSX タグを返したい場合に別のタグかフラグメントでラップしないといけないのも、同じ理由です
まとめ
公式より
JSX と React は別の物です。一緒に使われることが多いですが、片方だけを独立して使うことは可能です。JSX とは言語の拡張であり、React は JavaScript ライブラリです。
普段書いているReact
がいかに純粋なJavaScript
であるかがわかりますね。
最後に
ここまで見ていただきありがとうございます!🙇
JSX
について知らなくても直感的に書けますが、知っているとよりReact
と仲良くなれたような気がします。
参考
組み込みコンポーネント
DOMコンポーネント
interface IntrinsicElements
HTML を JSX に変換する