先生、どうしてReactでは class ではなくて className を使うの？


## 問い
どうして`React`では`class`でなく`className`を使うのか？

## 結論
`class`は `JavaScript` の予約語になっているため、やむを得ず `className` に改名している。

## JSXとは
まず前提知識として、**JSXについて少し知っている必要があります。**

`JSX`とは**jsの中にxmlライクな記述ができるようになった拡張構文で、**

ブラウザで実行される前に、**jsオブジェクトを生成する式**に変換します。

例えば、以下のような`JSX`があるとします。
```jsx
const button = <button type="submit" onClick={() => alert('クリックされました')}>送信</button>;
```

これは、ブラウザで実行される前に以下の`js`に変換されます。

```js
const button = React.createElement(
  "button",
  { type: "submit", onClick: () => alert('クリックされました') },
  "送信"
);
```
つまり、**`react`における`JSX`とは、`React.createElement`を生成する記法ということになります。**

[React.createElement](https://ja.react.dev/reference/react/createElement)は公式にも説明がある通り、`React`の要素を生成する`ReactAPI`なので、`JSX`から返却されるオブジェクトによって`React`要素が生成されます。

## `JSX`ファイルの中で`HTML`っぽく書けるのに、実は`HTML`のプロパティとは全くの別物だった...!!

話は戻り、どうして`React`では`class`でなく`className`を使うのか？


`JSX`は`js`に変換されるので、**JSX内でclassを使用するとjsのプロパティとして解釈されます。**

しかし、**jsには [class](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes) の予約語が存在しているのでJSXでclassが使用されるのを避けています。**

ちなみに同じ理由で改名を余儀なくされているのが `for` で、`htmlFor`に改名されています。




## 以下余談

## 組み込みコンポーネント
Reactのコンポーネントには、以下の2種類が存在します
- ユーザー定義コンポーネント
- 組み込みコンポーネント

[公式が公開している<Fragment>](https://ja.react.dev/reference/react/components)のような組み込みコンポーネント以外に、
[DOMコンポーネント](https://ja.react.dev/reference/react-dom/components)もサポートしています。

以下のように一見、`標準HTML`タグに見える`div`や`p`が**組み込みコンポーネント**に当たります。
```tsx
const content = <div className="wrapper">Some content</div>
```

`div`にカーソルを当ててみると、それなりの`prop`を受け取ることができます。

<img width='600px' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2508607/aaa26253-4bde-1f66-26cd-52ad873adf38.png' />

このpropsの型の在処は[interface IntrinsicElements](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L4342)に定義されています。


※ ちなみに、`Intrinsic`は`「〔人・物に〕本来備わっている、固有の、本質的な」`という意味があります。

`div`なら以下のように定義されており、
```jsx
div: React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
```
`React.HTMLAttributes`は以下のように定義されている。
```jsx
    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 タグを返す時にフラグメントでラップする

周知ですが、以下のようなコンポーネントではエラーが発生しますね。
```jsx
export function Item() {
  return (
    <input type="text" placeholder="名前を入力" />
    <button type="submit" onClick={() => alert('クリックされました')}>送信</button>
  );
}

```

`JSX`は単一のタグを返却するというルールがあるので以下のような修正を加えるはずです。
```jsx
export function Item() {
  return (
    <>
      <input type="text" placeholder="名前を入力" />
      <button type="submit" onClick={() => alert('クリックされました')}>送信</button>
    </>

  );
}

```
**エラーになるからとりあえず従ったけど、どうしてなのか？**


前述した通り、`JSX` は `HTML` のように見えますが、「最終的には`JavaScript`オブジェクトに変換される」ということが分かっているならこれも理解できます。

[公式のコラム](https://ja.react.dev/learn/writing-markup-with-jsx#converting-html-to-jsx)に説明がありました。
>関数から 2 つのオブジェクトを返したい場合、配列でラップしないといけませんよね。2 つの JSX タグを返したい場合に別のタグかフラグメントでラップしないといけないのも、同じ理由です


## まとめ
公式より
>JSX と React は別の物です。一緒に使われることが多いですが、片方だけを独立して使うことは可能です。JSX とは言語の拡張であり、React は JavaScript ライブラリです。

普段書いている`React`がいかに純粋な`JavaScript`であるかがわかりますね。
## 最後に
ここまで見ていただきありがとうございます！🙇
`JSX`について知らなくても直感的に書けますが、知っているとより`React`と仲良くなれたような気がします。



## 参考
[組み込みコンポーネント](https://ja.react.dev/reference/react/components)
[DOMコンポーネント](https://ja.react.dev/reference/react-dom/components)
[interface IntrinsicElements](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L4342)
[HTML を JSX に変換する 
](https://ja.react.dev/learn/writing-markup-with-jsx#converting-html-to-jsx)