React入門 01: コンポーネントを組み立てる
Tags: javascript, webdev, tutorial, react
Published: 2019-06-25 01:42:03

---
title: React入門 01: コンポーネントを組み立てる
published: true
description: ReactはFacebook社により開発が進められている、もっとも注目度の高いJavaScriptフレームワークのひとつです。DOMの要素をデータと関連づけて(データバインディング)、データの変化に応じてページを動的に構成します。
tags: #javascript, #webdev, #tutorial, #react
---

[React](https://ja.reactjs.org/)はFacebook社により開発が進められている、もっとも注目度の高いJavaScriptフレームワークのひとつです。[DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction)(Document Object Model)の要素をデータと関連づけて(データバインディング)、データの変化に応じてページを動的に構成します。

そして、アプリケーションの機能は小分けして、それぞれのデータの処理とテンプレートをまとめたものがコンポーネントです。小さなコンポーネントを組み合わせて、ひとつのシステムがつくられます。コードはコンポーネントごとに確かめればよいので、読みやすく、メンテナンスもしやすくなるのです。

ただ、なじみの少ない構文の知識や準備が求められるため、初めての方には少し始めにくいかもしれません。本稿では、簡単なコンポーネントを組み合わせて、シンプルなシングルページアプリケーション(SPA)をつくってみます。


# Create React Appでアプリケーションのひな形をつくる
「[Create React App](https://ja.reactjs.org/docs/create-a-new-react-app.html#create-react-app)」は、シングルページアプリケーション(SPA)のひな形をつくってくれる開発環境です。このひな形に手を加えて目的のアプリケーションにします。

まずは、[Create React Appのインストール](https://reactjs.org/blog/2016/07/22/create-apps-with-no-configuration.html)です。予めNode.js(npm)が入っていなければなりません。コマンドラインツールからnpmでつぎのコマンドを打ち込んでください。

```terminal
npm install -g create-react-app
```

`npx create-react-app`または`create-react-app`コマンドにつづけてアプリケーション名を入力すると、その名前でフォルダとアプリケーションのひな形がつくられます。

```terminal
npx create-react-app react-comment-box
```

ひな形がつくられたら、アプリケーションのディレクトリに移って、`npm start`とコマンドを打てば、ローカルサーバーでひな形のページが開きます(図001)。

```terminal
cd react-comment-box
npm start
```

#### 図001■Reactのひな形アプリケーションページ
![01_001.png](https://thepracticaldev.s3.amazonaws.com/i/ansf16dqqcbh9nfi6wso.png)

アプリケーションのディレクトリには、つぎのようなファイルがつくられます(図002)。この中で手を加えるのは、`src/App.js`と`src/App.css`です。

#### 図002■アプリケーションのディレクトリにつくられたファイル
![01_004.png](https://thepracticaldev.s3.amazonaws.com/i/qh0mstwgukaybg2bptbn.png)


# アプリケーションに子コンポーネントを加える
`src/App.js`は大もとになるコンポーネントです。ひな形アプリケーションには、ほかのコンポーネントはまだありません。つぎのJavaScriptコードの抜書きが、軸となる枠組みです。まず、スタイルシートのファイル(`App.css`)を`import`しています。コンポーネント(`App`)を定めるのは、関数です(「[関数コンポーネントとクラスコンポーネント](https://ja.reactjs.org/docs/components-and-props.html#function-and-class-components)」参照)。そして、[JSX](https://ja.reactjs.org/docs/glossary.html#jsx)で定められたDOMのテンプレートを返さなければなりません([JSX の導入](https://ja.reactjs.org/docs/introducing-jsx.html)」参照)。

```react
import React from 'react';
import './App.css';

function App() {
  return (
    <div className="App"><!-- JSXのテンプレート -->
      <!-- 中略 -->
    </div>
  );
}

export default App;
```

JSXのテンプレートは、基本的にはHTML(XML)の書き方に添います。ただし、`class`属性は`className`に替えなければなりません。[`class`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/class)が[ECMAScript 2015の予約語](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Lexical_grammar#キーワード)になっているためでしょう。また、テンプレートは必ずひとつのルート要素にまとめてください。

`src/App.js`のコードはつぎのように書き替えます。`import`に加えたのは、このあとにつくる子コンポーネント(`CommentList`)です。これを、テンプレートにタグとして加えています。なお、ファイル`src/logo.svg`は要らなくなりましたので、フォルダから削って構いません。

```react
import React from 'react';
import CommentList from './components/CommentList';
import './App.css';

function App() {
  return (
    <div className="App">
      <h1>コメント</h1>
      <CommentList />
    </div>
  );
}

export default App;
```

子コンポーネントは`src/components/CommentList.js`として、つぎのように定めます。枠組みの記述は同じで、コンポーネントをアロー関数式で定めたのとテンプレートにテキストの要素が加わっただけです。

```react
import React from 'react';

const CommentList = () => {
  return (
    <div className="CommentList">
      <h2 className="CommentAuthor">
      ヘンリー・キッシンジャー
      </h2>
      チャンスは貯金できない。
    </div>
  );
};

export default CommentList;
```

CSSファイル`src/App.css`は、つぎのコード001のように書き替えましょう。あとで使うクラスも、すでに加えてあります。ブラウザで読み込み直すと、ページが描き改められるでしょう。子コンポーネント(`CommentList`)のテキストが表示されるはずです(図003)。

#### コード001■`src/App.css`
```css
h1 {
  border-bottom: 1px solid #ddd;
}
.App {
	margin-left: 20px;
	margin-right: 20px;
}
.CommentList {
  margin-bottom: 10px;
}
.CommentForm {
  margin-top: 20px;
}
.CommentForm input {
  font-size: 12px;
}
.Comment {
  margin-bottom: 10px;
  font-size: 16px;
}
.CommentAuthor {
  border-bottom: 1px solid #ddd;
  margin: 0;
}
.CommentText {
  display: flex;
  align-items: center;
}
```

#### 図003■ページに子コンポーネントのテキストが表示される
![01_005.png](https://thepracticaldev.s3.amazonaws.com/i/gdkxx1qvo05pkjatvi6y.png)


# さらにコンポーネントに切り出す
コンポーネント`src/components/CommentList.js`のテンプレートに加えた`<div>`要素(`className`属性`CommentList`)は、複数リストにするつもりです。そのために、この部分は別のコンポーネント(`Comment`)に切り出しましょう。そして、`<h2>`要素に加えるテキストは、タグに属性(`author`)として与えます。この値は、子コンポーネントから取り出すことができるのです。

```react
import Comment from './Comment';

const CommentList = () => {
  return (
    <div className="CommentList">
      {/* <h2 className="CommentAuthor">
      ヘンリー・キッシンジャー
      </h2>
      チャンスは貯金できない。 */}
      <Comment author="ヘンリー・キッシンジャー">チャンスは貯金できない。</Comment>
      <Comment author="マーク・トウェイン">禁煙なんてたやすい。私は何千回もやった。</Comment>
    </div>
  );
};
```

切り出す子コンポーネント`src/components/Comment.js`の定めは、つぎのコード002のとおりです。親のテンプレートから与えられた値は、子コンポーネントの関数が引数(`props`)に受け取ります(「[関数コンポーネントとクラスコンポーネント](https://ja.reactjs.org/docs/components-and-props.html#function-and-class-components)」参照)。属性値は属性名で、子要素は`props.children`で、つぎのコード002のように波かっこ`{}`にくくって参照してください(「[子要素の出力 (Containment)](https://ja.reactjs.org/docs/composition-vs-inheritance.html#containment)」参照)。`{}`の中はJavaScriptコードとして評価されます。

#### コード002■`src/components/Comment.js`
```react
import React from 'react';

const Comment = (props) => {
  return (
    <div className="Comment">
      <h2 className="CommentAuthor">
      {props.author}
      </h2>
      {props.children}
    </div>
  );
};

export default Comment;
```


# 子コンポーネントをもうひとつ加える
子コンポーネント(`CommentForm`)をもうひとつ、大もとのアプリケーション(`src/App.js`)に加えましょう。

```react
import CommentForm from './components/CommentForm';

function App() {
  return (
    <div className="App">

      <CommentForm />
    </div>
  );
}
```

`src/components/CommentForm.js`に書くのは、つぎのコード003のとおりで、まだダミーの状態です。

#### コード003■`src/components/CommentForm.js`
```react
import React from 'react';

const CommentForm = () => {
  return (
    <div className="CommentForm">
      CommentFormを表示
    </div>
  );
};

export default CommentForm;
```

これで、コンポーネントに切り分けたコメントがふた組と、あとから加えたコンポーネントのダミーのテキストがページに表示されます(図004)。

#### 図004■ふた組みのコメントとダミーテキストがページに表示される
![01_006.png](https://thepracticaldev.s3.amazonaws.com/i/fneykf4h0nz3qpbat99g.png)

以下に、手直しした`src/App.js`(コード004)と`src/components/CommentList.js`(コード005)をまとめて掲げます。

#### コード004■`src/App.js`
```react
import React from 'react';
import CommentList from './components/CommentList';
import CommentForm from './components/CommentForm';
import './App.css';

function App() {
  return (
    <div className="App">
      <h1>コメント</h1>
      <CommentList />
      <CommentForm />
    </div>
  );
}

export default App;
```

#### コード005■`src/components/CommentList.js `
```react
import React from 'react';
import Comment from './Comment';

const CommentList = () => {
  return (
    <div className="CommentList">
      <Comment author="ヘンリー・キッシンジャー">チャンスは貯金できない。</Comment>
      <Comment author="マーク・トウェイン">禁煙なんてたやすい。私は何千回もやった。</Comment>
    </div>
  );
};

export default CommentList;
```