Reactの基本的な構造
Reactを構成する3つのファイル
Reactアプリケーションには、基本的にいくつかのファイルが生成されている。
Reactを構成する3つのファイル
その中で、アプリケーション本体を構成するファイルは3つある。それぞれの役割を説明する。
-
index.js
srcフォルダに含まれている。メインプログラムといえる。ここでHTMLテンプレートとJavaScriptのコンポーネントを組み合わせ、レンダリングして実際に表示する。
-
App.js
srcフォルダにある。これはコンポーネントを定義するプログラムである。実際に画面に表示される内容などはここで定義される。
-
index.html
publicフォルダにある。メインプログラムであるindex.jsに対応するHTMLテンプレートファイルである。このファイルが直接表示されるのではなく、index.jsによって読み込まれ、レンダリングされた結果が表示される。
ビルドすると構成が変わる
注意すべき点は、これらはNode.jsアプリケーションとして動作する場合の構成であるということだ。サーバーにNode.jsがあり、そのまま起動するのであればこのままでもよいが、通常のWebサーバーに配置して使う場合、アクセス時にindex.jsが読み込まれてレンダリングされる方法は少し無理がある。
このような場合は、前に説明したようにnpm run buildでアプリケーションをビルドする。するとフォルダ構成が変わる。フォルダのルートにindex.htmlが新しく生成され、その中でindex.jsに相当するスクリプトが実行された表示を作れるようになる。
実際に試してみれば分かるが、index.htmlはともかく、そこから呼び出されるスクリプトはビルド時に新しく生成され、コード自体がまったく異なるものになっている。自動生成されているためか改行もなく、人が読むには難しい。つまり、ビルドして生成されたものは、もはや「人が編集するもの」とは考えないということである。一般的なプログラミング言語ではソースコードをコンパイルするとバイトコードを生成するが、それに近いものだと考えればよい。
したがって、私たちがプログラミングするのはあくまでビルド前のindex.jsやApp.jsである。修正する場合もこれらを編集し、再度ビルドして生成されたものを配布する。これまでの「HTMLやJavaScriptは書いたものがそのままサーバーにアップロードされ、ブラウザに読み込まれて動作する」という常識は捨てる必要がある。
Reactでは「開発時に書くコード」と「実際に配布されるコード」はまったく異なる。Reactはコンパイラ言語で開発するような感覚で作る必要がある。
(ただし、Node.jsそのものがサーバーにあり、Node.jsアプリケーションとして実行するのであれば話は別である。この場合はいわばインタープリタがサーバーにあり、コンパイルしなくても動作するような状況だと考えてよい)
index.jsアプリケーションのプログラム
生成されたソースコードを見てみよう。
アプリケーションのプログラムについて
メインプログラムであるindex.jsを説明する。以下にソースコードを示し、内容を順番に説明する。
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
import文について
最初に複数のimport文が書かれているが、これは外部モジュールをロードするものである。このimport文はJavaScriptではあまりなじみがないかもしれないが、ES6、つまりECMAScript 6 Editionでサポートされる機能である。Reactでは「Babel」というES6対応のトランスコンパイラを使っているため、このようなES6の機能を利用できる。
最初にreact、react-domというモジュールをロードしており、これらがReactの本体である。また、次の./App、./index.cssはここで使用するコンポーネントとスタイルシートである。これらもimportでロードする。
ReactDOM.render
次に、ReactDOMオブジェクトのrenderメソッドを実行している。これはこのプログラムで実行する唯一の処理である。コンポーネントを指定した位置に入れてレンダリングを行うもので、次のように実行する。
ReactDOM.reder(コンポーネント, 組み込み先要素);
第1引数には、App.jsで定義しているAppコンポーネントを指定している。そして第2引数には、rootというIDの要素を指定する。すると、Appコンポーネントがrootタグに含まれたコードとしてレンダリングされ、出力される。
JSXについて
ここではrenderの引数に<App />というものが指定されている。これはAppコンポーネントのタグだが、JavaScriptの引数に直接HTMLタグが書かれているため、不思議に思うかもしれない。
これはJSXという機能を利用したものである。おそらく「JavaScript Expression」の略だろう。このJSXは、HTMLタグをそのままJavaScriptコード内に書ける機能である。単独タグだけでなく、タグの中に別のタグが含まれる複雑なものも処理できる。
<App />という値を書くことで、<App />タグに定義されたユーザー定義コンポーネントをrenderに指定している。
index.htmlテンプレート
続いて、Webページのテンプレートであるindex.htmlを見てみよう。以下にソースコードを示す。長いコメントがあるが、ここでは省略した。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
... 中略 ...
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
... 中略 ...
-->
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
... 中略 ...
-->
</body>
</html>
このコードはそれほど難しくない。いくつか説明する。
%PUBLIC_URL%について
ヘッダー部分を見ると、<link>タグにhref="%PUBLIC_URL%/favicon.ico"のような値が設定されている。この%PUBLIC_URL%はReactが提供する接頭辞で、公開サイトのURLが設定される。
id="root"タグについて
<body>部分に<div id="root"></div>というタグがある。このid="root"はどこかで見た覚えがあるはずだ。そう、index.jsのReactDOM.renderの引数でdocument.getElementById('root')として指定していたものである。指定したrootが、この<div id="root"></div>タグを指している。つまり、このタグ部分に<App />コンポーネントが含まれるようになっている。
このindex.htmlテンプレートの役割はこれだけである。ただ<div id="root"></div>タグを用意し、ここにコンポーネントが含まれるテンプレートである。
App.js Appコンポーネント
アプリケーションの表示部分は「コンポーネント」によって作られる。このソースコードがどうなっているか見てみよう。
基本的にApp.jsというスクリプトファイルが用意されており、ここにAppというコンポーネントのコードが記述されている。その内容を以下に示す。
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
export default App;
コードの内容を整理してみよう。
import文について
まずimport文で複数のモジュールを取り込んでいる。最初の行にimport React {Component} from 'react';という文があるが、これがReactのコンポーネント関連のオブジェクトをロードする部分である。その後の2行は、logo.svgとApp.cssをロードするための文である。
Appクラスについて
ここではAppクラスというものが定義されている。JavaScriptでもクラスを作成できる。ES6というエディションでクラス定義が可能になっている。ReactがES6であることを思い出そう。ここではAppクラスを次のように定義している。
class App extends Component {...}
Componentクラスを継承してAppクラスを生成していることが分かる。このComponentがコンポーネントの基盤となるクラスである。これを継承することでコンポーネントとして動作する。
renderメソッドについて
このAppクラスにはrenderというメソッドが1つ含まれている。これは次のように書かれる。
render () {
return ...;
}
returnで返される値が、そのままレンダリングの内容として処理される。ここではreturnする値は次のような形になっている。
return (<div className = "App"> ... 省略 ... </div);
HTMLタグが書かれている。これが「JSX」である。ここで返されるタグが、そのままAppコンポーネントの表示内容として出力される。
これでReactアプリケーションの基本的な内容が分かった。「コンポーネントを定義し、それを組み込んでレンダリングする」というのが、Reactで行っているすべてである。