クモのようにコツコツと

フロントエンドエンジニア イイダリョウのブログ。略称「クモコツ」

【React】JSX事始め「すごいぞ!JSXもCDNで動いたんだ!」

Reactの続きです。前回はReactの仮想DOMをCDNで体験しました。今回はJSXのコンパイルを同じくCDNで体験します。ReactといえばJSX!なイメージだったのでようやく一歩踏み入れた感。それでは行きましょう!

【目次】

前回記事
※参考:React事始め「すごいぞ!ReactはCDNで動いたんだ!」 - クモのようにコツコツと

Reactを習得するためにやったことまとめ qiita.com

前回のおさらい

前回作ったものはこちら。CDNリンクのためCodePenで作れている。

See the Pen React 02 by イイダリョウ (@i_ryo) on CodePen.

HTMLコード

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

react.development.jsreact-dom.development.jsをCDNで読み込むと

<section>
    <h1>りあくと事始め</h1>
    <div class="text">読み込み中…</div>
</section>

HTML上の.textの文字は「読み込み中…」でも…

JSコード

//DOM取得
const text = document.querySelector('.text');

//DOMの中身設定
const elm = React.createElement(
    'p', {}, 'こんにちは、りあくと。'
);

//レンダリング
ReactDOM.render(elm, text);

仮想DOMelmの文字が読み込まれて「こんにちは、りあくと。」が画面に表示される。

※参考:React事始め「すごいぞ!ReactはCDNで動いたんだ!」 - クモのようにコツコツと

仮想DOMを入れ子構造のタグにする

今回も掌田さんの「React.js & Next.js超入門 」を参考に進めています。

React.js&Next.js超入門

React.js&Next.js超入門

  • 作者:掌田 津耶乃
  • 出版社/メーカー: 秀和システム
  • 発売日: 2019/03/08
  • メディア: 単行本

上記の例では仮想DOMがpタグ一つだが、これを入れ子構造の親子階層タグにするとどうなるか。

See the Pen React 04 by イイダリョウ (@i_ryo) on CodePen.

JSコード

//DOM取得
const text = document.querySelector('.text');

//DOMの中身設定
const elm = React.createElement(
    'section', {class: "h2_elem"}, [
        React.createElement(
            'h2', {}, 'h2見出しです'  
        ),
        React.createElement(
            'p', {}, '入れ子で作られた仮想DOMですこれは。' 
        ),
        React.createElement(
            'ol', {}, [
                React.createElement(
                    'li', {}, 'リストの1番目'
                ),
                React.createElement(
                    'li', {}, 'リストの2番目'
                ),
                React.createElement(
                    'li', {}, 'リストの3番目'
                ),
                React.createElement(
                    'li', {}, 'リストの4番目'
                ),
            ]),
]);

//レンダリング
ReactDOM.render(elm, text);
  • 変数elmReact.createElement()の第3引数を配列に
  • 配列の中に入れ子でReact.createElement()を書く
  • 仮想DOMの階層上、並列な要素は同様に第3引数を配列にする
  • 属性(例:sectionのclass名.h2_elem)は第2引数の連想配列で指定する

なお、子要素は配列で並列表現できるが一番外側の親要素は一つでなければならない。どうしても複数要素になる場合は全体をdivで囲う。

元のHTMLコードは変えていないが…

<section>
    <h1>りあくと事始め</h1>
    <div class="text">読み込み中…</div>
</section>

画面上のHTMLコードはこうなっている。

<section>
    <h1>りあくと事始め</h1>
    <div class="text">
        <section class="h2_elem">
            <h2>h2見出しです</h2>
            <p>入れ子で作られた仮想DOMですこれは。</p>
            <ol>
                <li>リストの1番目</li>
                <li>リストの2番目</li>
                <li>リストの3番目</li>
                <li>リストの4番目</li>
            </ol>
        </section>
    </div>
</section>

この方法で入れ子構造の親子階層を作ることができるが、JSコードのネストが深くてあまり直感的ではなくなってしまう…

JSXとは何ぞや?

ということで「そうだ、JSX使おう!」となったわけです!はい。ところでJSXとは何ぞや?

JSXは、JavaScriptの構文に対する拡張である[11]。HTMLと外観が似ているが、JSXは多くの開発者がよく知っている構文を使用して、構造化されたコンポーネントを描画する方法を提供する。Reactコンポーネントは、必須ではないが、通常はJSXを使用して書かれている

※参考:React - Wikipedia

このJSXがHTMLの書式とソックリさん(細かい部分に違いはあるが)で、先ほどのネストの深い仮想DOMの階層をもっと直感的に表現することができる。

JSXってなんの略か

Reactで出てくるJavaScript syntax extension(以下、JSX)という単語

※参考:Reactで出てくるJSXという単語の意味 | エンジニアっぽいことを書くブログ

ふむ。シンタックスは「構文」でextensionは「拡張」という意味なので「JSの拡張構文」といった意味合いか。

CDNでJSXのライブラリを読み込む

そんでもってJSXのライブラリがまたまたCDNで読み込めるようだ!これによってローカル開発環境なしにCodePenで体験ができる。

以下のコードをheadタグに追加(CodePenの場合は「JavaScript Preprocessor」を「Babel」にすればOK!)

<script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>

なんと!JSXのライブラリって一つ前の記事で触れた「Babel」じゃないスか!!

※参考:【JS】BabelでESをコンパイルする - クモのようにコツコツと

BabelはES6以降の書式をES5にコンパイルするという理解だったがJSXのコンパイルも対応しているようだ!

もう一つ注意点としてはJSコードを書く部分のscriptタグにbabelの属性を追記する。

<script type="text/babel">
    //JSXで書かれたコード
</scirpt>

こうしないとJSXで書かれた部分が認識されない。エラー(“Uncaught SyntaxError: Unexpected token <”)になってしまった。

※参考:javascript - ReactJS: "Uncaught SyntaxError: Unexpected token <" - Stack Overflow

(先ほど書いたようにCodePenは「JavaScript Preprocessor」を「Babel」にすればOK!)

JSXコードを書く

JSコードをJSX書式に書き換える

//DOM取得
const text = document.querySelector('.text');

//JSXの中身
const elm = (
<section class="h2_elem">
    <h2>h2見出しです</h2>
    <p>入れ子で作られた仮想DOMですこれは。</p>
    <ol>
        <li>リストの1番目</li>
        <li>リストの2番目</li>
        <li>リストの3番目</li>
        <li>リストの4番目</li>
    </ol>
</section>
);

//レンダリング
ReactDOM.render(elm, text);

変数elmを先ほどブラウザ画面でレンダリングされていたHTMLと同じ内容に差し替える。見た目がとてもシンプル!

全体を囲っているカッコ()は無くても認識されるがJSXの境界をわかりやすくするために書いている。また、JSXでも一番外側のタグは一つだけなので一つにできない場合は全体をdivで囲う。

コンパイル後のJSコード

ちなみにCodePen上でコンパイル後のJSコード(「Vew Compiled JS」)を見るとこうなる。

//DOM取得
const text = document.querySelector('.text');

//h2テキスト
const h2Text = "JSXはじめました";

//pタグテクスト
const pText = "JSXに埋め込まれた値ですこれは。";

//JSXの中身
const elm =
React.createElement("section", { class: "h2_elem" },
React.createElement("h2", null, h2Text),
React.createElement("p", null, pText),
React.createElement("ol", null,
React.createElement("li", null, "\u30EA\u30B9\u30C8\u306E1\u756A\u76EE"),
React.createElement("li", null, "\u30EA\u30B9\u30C8\u306E\uFF12\u756A\u76EE"),
React.createElement("li", null, "\u30EA\u30B9\u30C8\u306E3\u756A\u76EE"),
React.createElement("li", null, "\u30EA\u30B9\u30C8\u306E4\u756A\u76EE")));

//レンダリング
ReactDOM.render(elm, text);

やはりReact.createElement()のネストが入り組んでいて直感的ではない。

JSXに値を埋め込む

このままだとJSの中にただHTMLを埋め込んでいるだけなのでもう少しJSらしい動きを体験したい。JSXの中に外側の変数の値を埋め込んで見る。

See the Pen React 06 by イイダリョウ (@i_ryo) on CodePen.

見た目はほとんど同じだがJSXの部分を変えている。

//DOM取得
const text = document.querySelector('.text');

//h2テキスト
const h2Text = "JSXはじめました";

//pタグテクスト
const pText = "JSXに埋め込まれた値ですこれは。";

//JSXの中身
const elm = (
<section class="h2_elem">
    <h2>{ h2Text }</h2>
    <p>{ pText }</p>
    <ol>
        <li>リストの1番目</li>
        <li>リストの2番目</li>
        <li>リストの3番目</li>
        <li>リストの4番目</li>
    </ol>
</section>
);

//レンダリング
ReactDOM.render(elm, text);
  • 変数h2Texth2タグに入れたいテキストを代入
  • 変数pTextpタグに入れたいテキストを代入
  • JSXのh2タグの中にh2Textを配置
  • JSXのpタグの中にpTextを配置

JSX内に変数を配置する時は全体を波括弧{ }で囲う。Vue.jsは二重波括弧{{ }}だったがReactは一重のようだ。

JSXのタグの中に属性を埋めこむ

今度はタグの中に属性を埋め込んでみる。aタグを作ってsrc属性に値を埋め込む。

See the Pen React 07 by イイダリョウ (@i_ryo) on CodePen.

JSコード

//DOM取得
const text = document.querySelector('.text');

//JSXに埋め込む値
const h2Text = "JSX始めました";
const pText = "JSXに埋め込まれた値ですこれは。";
const ggrks = "わからないことはググろう";
const url = "https://www.google.com/";

//JSXの中身
const elm = (
<section class="h2_elem">
    <h2>{ h2Text }</h2>
    <p>{ pText }</p>
    <p><a href={ url } target="_blank">{ ggrks }</a></p>
</section>
);

//レンダリング
ReactDOM.render(elm, text);
  • 変数ggrksにテキスト「わからないことはググろう」を代入
  • 変数urlにテキスト「https://www.google.com/」を代入
  • リストをpタグに変更してaタグを入れる
  • aタグのhref属性にurlを埋め込み、テキストにggrksを埋め込む。

属性に埋め込む際は" "で囲う必要がないのがポイント。

JSXのタグにstyle属性でCSSスタイルを当てる

CSSを設定する方法はいくつかある。

  • 外部のcssファイルをlink属性でリンクする
  • styleタグで囲った中にスタイルを書く
  • 一つ一つのタグの中にstyle属性でスタイルを書く

通常は外部のcssファイルに書くことが多いが、Reactはタグの中にstyle属性で書くことが多いらしい。(昔のテーブルレイアウト時代を思い出す書き方だがスタイルの値は直書きではなく外部変数で共通化するため、メンテナンス上の不便はない)

やってみたのがこちら。

See the Pen React 08 by イイダリョウ (@i_ryo) on CodePen.

aタグ「わからないことはググろう」にスタイルを当ててボタンにした。

//DOM取得
const text = document.querySelector('.text');

//JSXに埋め込む値
const h2Text = "JSX始めました";
const pText = "JSXに埋め込まれた値ですこれは。";
const ggrks = "わからないことはググろう";
const url = "https://www.google.com/";

//CSS設定
const ggrks_s = {
    display: "block",
    padding: "10px",
    borderRadius: "5px",
    textAlign: "center",
    color: "#fff",
    background: "#A63744",
    textDecoration: "none",
}

//JSXの中身
const elm = (
<section class="h2_elem">
    <h2>{ h2Text }</h2>
    <p>{ pText }</p>
    <p><a href={ url } target="_blank" style={ ggrks_s }>{ ggrks }</a></p>
</section>
);

//レンダリング
ReactDOM.render(elm, text);
  • 変数ggrks_sに連想配列でスタイルを設定
  • JSXのaタグのstyle属性にggrks_sを埋め込む

スタイルはパッと見CSSにソックリだがよく見ると違いがある。

  • 連想配列なので値の区切りはセミコロン;では無くカンマ,
  • 値はダブルコーテーション" "で囲う
  • プロパティ名が複数単語の場合ケバブケース(ハイフン-)では無くキャメルケース(大文字)で繋ぐ

キャメルケース、ケバブケース、スネークケース(アンダースコア_)の違いについてはこちら

※参考:【極小ネタ】キャメルケース/スネークケース/チェーンケースの覚え方【変数の命名規則】 - Qiita

最後に

f:id:idr_zz:20200112203322p:plain

ということでJSXの基本的な部分を事始めました。BabelのCDNリンクでコンパイルできることは今回初めて知りました!

JSXは実際に始める前はJSコードの中にHTMLコードが組み込まれていることに違和感を感じていたのですが、こうしてReact.createElement()の書式と比較してみるとやはりJSXの方がシンプルでわかりやすいと感じました。それに基本はDOMの階層構造のテンプレートなんだな、とイメージできました。

次回はJSXに関数を組み込んでみようと思います。それではまた!


Reactを習得するためにやったことまとめ qiita.com