[React] よーし! いっちょReactやってみっか! #4 書いてみよう編

2020.10.06

はじめに

CX事業本部の中安です。まいどです。

モバイルアプリエンジニアな自分がReactを始めてみることにした 「よーし! いっちょReactやってみっか!」シリーズの続きです。 今回もよろしくお願いします。

前回Reactでよく使われる基本キーワードをまとめてみました。

今回からは実際にReactのソースコードを書いていってみましょう。

HTMLファイルで書いてみよう

初回のブログでは、npxコマンドを使ってReactプロジェクトを作り、それを起動することでブラウザでWEBアプリを確認することができました。

では、そういう形でないとReactは使えないのかというと、そうではないです。 1つのシンプルなHTMLファイルだけでもReactは利用可能です。

それでは、基本を習得すべくHTMLファイルを使ってReactのソースコードへの実装を体感してみたいと思います。

ベースのHTML

今回index.htmlファイルを作り、以下のようなHTMLをベースとして用意しました。

index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Reactのテスト</title>
  </head>
  <body>  
  </body>
</html>

なんの変哲もないHTMLですね。 ブラウザで開いてみても真っ白なページだと思います。(タイトルは設定されていますが)

CDNリンクを使う

React

ここにReactを使用する場合は、reactreact-domという2つのライブラリを読み込むことが必要です。 その読み込み方法としてCDNリンクを使うことができます。

開発用としてのdevelopment.jsと、本番用のmin.jsが用意されていますが、 今回はdevelopment.jsを使うこととします。

index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Reactのテスト</title>
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  </head>
  <body>  
  </body>
</html>

ハイライトされている<script>が変更した箇所です。@16とされているところは現時点のバージョンなので、この記事が古くなっていたら差し替わる可能性があります。バージョンを特定する時なども適宜書き換えてください。

最新のバージョンやcrossorigin属性の必要性などはこちらを参考ください。

Babel

JSXの利用にはBabelが必要であることは前回書きました。こちらもCDNリンクで読み込みます。

index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Reactのテスト</title>
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.js"></script>
  </head>
  <body>  
  </body>
</html>

こちらも開発用としてのbrowser.jsと、本番用のbrowser.min.jsが用意されているようですね。

Body部の追記

<body>内にアプリケーションの基礎部分を書いていきましょう。

np script タグ

JavaScriptが実行されない環境への対応のため<noscript>タグを埋め込みます。 内容は各自お任せしますが、今回は以下のように書きます。

<noscript>You need to enable JavaScript to run this app.</noscript>

ルートタグ

Reactの場合、HTMLにUI要素をいくつも書き連ねるという手段は取りません。その役割はJavaScriptが行います。 ではHTMLの方はどうするかというと、ルートタグとしてひとつの<div>タグを用意するのがセオリーのようです。 この<div>の中をDOM操作によって差し替える形でアプリケーションは動いていくわけですね。

ですので、以下のタグを<body>の中に配置します。

<div id="root"></div>

ここまでのHTML

あらためて上記2つを実装した形が以下のようになります。

index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Reactのテスト</title>
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.js"></script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

scriptタグでReactを使う

ここでいよいよReactを使った実装をしていこうと思います。

まずは、スクリプトを書いていくために<script>タグを用意するのですが、前回のブログBabelの項にも書いたとおりタイプ指定が必要になります。

JSXが使えるようにするためには<script type="text/babel">と指定してください。

index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Reactのテスト</title>
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.js"></script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <script type="text/babel">
        // あとで書く
    </script>
  </body>
</html>

HTMLの準備はこんなものなので、ここからはスクリプトだけに注視しましょう。 以降はこの<script type="text/babel">内の実装になります。

ルートタグを取得

先程用意したルートタグをスクリプト側で取得するようにします。 この取得はJavaScript元来の標準機能を使用します。

ネット上ではgetElementByIdを使うパターンとquerySelectorを使うパターンが見受けられますが、 公式のチュートリアルではgetElementByIdを使っているようなのでこちらを採用しますね。

let dom = document.getElementById('root');

両者の違いはこのあたりを参考ください。

ReactDOM

取得したルートタグDOMに対して作成したコンポーネントをレンダリングしていくことがReactの基本的な流れになります。 いかに色々コンポーネントを組み合わせても、この作業がなければ画面は真っ白のままです。

このレンダリングの作業を行うのがReactDOMという登場人物で、このReactDOMrenderメソッドを呼び出すことで描画が実行されます。

ReactDOM.render()のシグネチャはこのような形です。

ReactDOM.render(描画する内容, 描画する先, [コールバック]);

では、試しに使ってみます。

let dom = document.getElementById('root');
ReactDOM.render(
  <h1>Hello World!</h1>,
dom);

改行していて読みにくければすいません。 描画する内容(第1引数)にはJSX構文を、描画する先(第2引数)にはルートタグdomを指定しています。

通常のHTMLを書く時も当然気をつけなければなりませんが、 JSXの場合は閉じタグなどが抜けているとシンタックス(構文)エラーが吐き出されます。 閉じ忘れたりすると、ブラウザがよしなに解釈してくれるわけもなく(そもそもブラウザを通過してない)、真っ白になりますので注意しましょう。

さて、ブラウザで再読み込みをしてみると大きく「Hello World!」が表示されると思います。

おめでとう。これで僕もReact使いだ!

コンポーネントを使う

ただ、まぁこれだけだと何もReactっぽくないですね。 色々とやりたいところですがReactの特長である「コンポーネント」を使ってみましょう。

関数コンポーネント"Hello"

先程「Hello World!」を表示していた<h1>要素をコンポーネント化してみます。 名前は適当に「Hello」という関数コンポーネントにします。

ソースコードを以下のように書き換えます。

const Hello = (props) => {
  return <h1>Hello World!</h1>
}

let dom = document.getElementById('root');
ReactDOM.render(
  <Hello />,
dom);

ブラウザをリロードしてみても「Hello World!」の表示は変わらず表示されると思います。 まずはコンポーネント化に成功しました。

※「何だ? この Hello = (props) => {} って書き方は?」ってなった方は前回のブログの「関数コンポーネント」の項を参考ください。

値を書き換える

propsの仕組みを使って外部からコンポーネント内の表示内容を変更できるようにしてみます。 propsはコンポーネントの属性に与えられた値がオブジェクトとなって渡されるという仕組みでした。

まずは、引き取る側のコンポーネントの改修です。

const Hello = (props) => {
  return <h1>Hello {props.name}!</h1>
}

このように{}括弧(ブレス)で囲った箇所は変数がバインドされるようになります。 propsnameという値が入ることになります。

この時点でブラウザをリロードしてみると「Hello !」という表示になると思います。 nameが与えられなくても特にエラーが生じるわけではないようです。

では、渡す側の改修もします。

let dom = document.getElementById('root');
ReactDOM.render(
  <Hello name="Developers.IO" />,
dom);

Helloコンポーネントの属性値にnameを与えました。 すると、ブラウザのリロードで「Hello Developers.IO!」という表示になると思います。

すごく簡単な例ですが、propsの使い方が分かりましたね。

JSXの注意点

調子に乗ってレンダリングの箇所にもう1個コンポーネントをこんな感じに表示させたくなりました。

let dom = document.getElementById('root');
ReactDOM.render(
  <Hello name="Developers.IO" /><Hello name="Classmethod" />,
dom);

こうすれば 「Hello Developers.IO! Hello Classmethod!」 と表示されるはず・・・。

しかし、これはエラーが生じてしまいます。残念。

JSX構文としては複数のエレメントを並列に置いて返すことができないのです。

複数エレメントのコンポーネントを作る際には、<div>タグなどで囲って1つのDOMになるように指定するよう注意することが必要ですね。

let dom = document.getElementById('root');
ReactDOM.render(
  <div>
    <Hello name="Developers.IO" />
    <Hello name="Classmethod" />
  </div>,
dom);

これで 「Hello Developers.IO! Hello Classmethod!」 と表示されると思います。

ここまでのソースコード

とりあえずコピペで動くと思いますが、写経が大事ですよっ (CDNはコピーでいいですけど)

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Reactのテスト</title>
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.js"></script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <script type="text/babel">
      const Hello = (props) => {
        return <h1>Hello {props.name}!</h1>
      }
        
      let dom = document.getElementById('root');
      ReactDOM.render(
        <div>
          <Hello name="Developers.IO" />
          <Hello name="Classmethod" />
        </div>,
      dom);
    </script>
  </body>
</html>

最後に

ここまでで単独のHTMLファイルでReactを使う環境を作り、 コンポーネントを作って、属性値を渡すところまでを実際にソースコードに落としてみました。

まだまだ初級編って感じが続くかと思いますが、どうぞお付き合いください。

では、またー。