React入門 - 4. コンポーネントの定義

4. コンポーネントの定義

Reactプログラミングの準備ができたので、まずは画面に "Hello World!" と出力してみようと思います。Reactでは画面に表示するプログラムをコンポーネントと呼ばれる単位で定義します。コンポーネントの定義にはクラスを使う方法(クラスコンポーネント)と関数を使う方法(関数コンポーネント)の2とおりの方法が用意されていますが、最近は関数コンポーネントによる定義が主流になっています。関数コンポーネントは後で学習するReack Hooksという仕組みを組み合わせることで効率よく開発できるようになっています。ここでは画面に "Hello World!" を出力する Hello コンポーネントを定義することにします。

Hello コンポーネントを作成する前に create-react-app で作成したアプリケーションが動作する仕組みから確認していきましょう。

前節で学習したとおり create-react-app で作成したReactアプリケーションは npm start コマンドを入力することで、開発サーバを起動できます。

% npm start

このときブラウザを起動して http://localhost:3000 にアクセスすると次のような画面が表示されるのでした。

ここで表示されているHTMLページはどこで定義されているのでしょうか。実はここで表示されているHTMLファイルは my-app/public フォルダに配置されている index.html ファイルです。VSCodeで public フォルダを開いて、index.html ファイルを確認してみましょう。


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

index.html ファイルはReactアプリケーションのテンプレートとなるHTMLファイルです。<head> タグの中にはアイコンやビューポートの設定、テーマカラーなどを確認できます。また <body> タグの中には <div id="root"></div> というタグを確認できます。これから学習していくようにJavaScriptによってReactで定義されたUIコンポーネントが、この id="root" と指定された <div> 要素に対して出力されるようになっています。Reactといっても特別なものではなく、JavaScriptプログラムであることに変わりはないので、画面を表示するためにはベースとなるHTMLファイルが必要になるのです。

これから学習していく範囲においては index.html ファイルを直接編集していくことはありません。画面のテンプレートとして index.html がブラウザに表示されている点を理解しておいてください。

次に src フォルダを開いて index.js ファイルを見てみましょう。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

index.js ファイルは create-react-app で作成したアプリケーションのエントリポイントとなるJavaScriptファイルです。つまり、index.js に記述したJavaScriptプログラムが先頭から順に実行されていくことになります。

index.js の先頭部分では必要なプログラムをインポートしています。reactreact-dom のような外部パッケージからのインポートの他、index.css ファイルのインポートなどを確認できます。その後の一文で src/App.js ファイルをインポートしています。

import App from './App';

ここで読み込んだ App 変数には App.js で定義された関数コンポーネントが代入されています。その後の処理で ReactDom.render メソッドを使って index.html ファイルの <div id="root"></div> に対してReactコンポーネントをレンダリングしています。

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

はじめてReactに触れる方は ReactDOM.render メソッドの引数に違和感があるかもしれません。

  <React.StrictMode>
    <App />
  </React.StrictMode>

JavaScriptプログラムの中にHTMLタグのようなものが定義されています。このような記述はJSXと呼ばれます。JSXで記述されたコードはコンパイラによってJavaScriptプログラムに変換されるようになっています。

<React.StrictMode></React.StrictMode> は古いAPIの利用など不正なコードを検出するために付与しています。

JSXの記述の中に <App /> コンポーネントの出力を確認できます。ここで出力される <App> コンポーネントを確認してみましょう。VSCodeで src/App.js ファイルを開きます。

import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

App.js ファイルの中ではインポート宣言のあとに App 関数の定義を確認できます。

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

これが <App /> コンポーネントの実装部分です。function キーワードによって定義された関数で return キーワードによって戻り値にJSXを返却しています。このような関数で定義されたコンポーネントを関数コンポーネントと呼びます。ここで定義した App コンポーネントは export default App; によって外部のJavaScriptプログラムからインポートして利用できるようになります。

コンポーネントはクラスを定義して実装することも可能です。

この App 関数で返却するJSXでは <div> タグや <header> タグ、 <img> タグなどを確認できます。ここで定義したJSXは最終的にJavaScriptコードに変換されてブラウザに出力されているのです。

Hello World!の出力

ここまでに create-react-app で作成したプロジェクトにおいて、複数のファイルがどのようにリンクしているかを確認しました。

  1. index.html
    • テンプレートとなるHTMLファイル
  2. index.js
    • JavaScriptプログラムのエントリポイント。index.htmlにJavaScriptコードを出力する
  3. App.js
    • index.js の中から参照されている関数コンポーネント

次に Hello.js という関数コンポーネントを作成して、ブラウザに Hello World! と出力してみようと思います。

まずはVSCodeで src フォルダを開いて Hello.js ファイルを作成します。

function Hello() {
    return (
        <h1>Hello World!</h1>
    )
}
export default Hello;

Hello.js ファイルでは function キーワードによって Hello という名前の関数コンポーネントを定義しています。関数の内部では return キーワードによってJSXで記述されたコンポーネントを返却しています。また外部のプログラムから Hello コンポーネントを利用できるようにさいごに export default Hello; を記述しています。

次に src フォルダの App.js を編集して、作成した Hello コンポーネントを出力してみましょう。

import logo from './logo.svg';
import './App.css';
import Hello from './Hello';

function App() {
  return (
    <Hello />
  );
}

export default App;

ここでは App 関数の実装を修正しています。以前の戻り値の定義部分を削除して、あらたに <Hello /> コンポーネントの定義を追加しています。以上でプログラムの修正は完了です。

動作確認

npm start によって開発サーバを起動した状態で、上記のようにプログラムを変更すると自動的にプログラムの変更を検出して、ブラウザがリロードされるようになっています。ブラウザを開いて画面(http://localhost:3000) を確認すると次のような結果を確認できるでしょう。

上記のように <Hello /> コンポーネントによる Hello World! というメッセージの出力を確認できます。Reactアプリケーションの開発では、このように関数コンポーネントやJSXを使って、画面の表示を定義していきます。Reactのコンポーネントには、上位のコンポーネントからデータを受けるために props とよばれるプロパティを受け取る仕組みが用意されています。次は props を使ったコンポーネントの定義について学習します。