React.jsでComponentsの分割をしてみる

# Components


コンポーネントを使用すると、UIを独立した再利用可能な部分に分割し、各部分について個別に考えることができます。概念的には、コンポーネントはJavaScript関数のようなものです。
# 関数とClassコンポーネント


コンポーネントを定義する最も簡単な方法は、JavaScript関数を記述することです。

```js
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
```

この関数は、データとともに単一の "props"オブジェクト引数を受け取り、React要素を返すため、有効なReactコンポーネントです。このようなコンポーネントは、文字通りJavaScript関数であるため、「機能的」と呼んでいます。また、[ES6](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes)クラスを使用してコンポーネントを定義することもできます。というか、これは現時点では古い書き方であり、古い書き方は、新しい書き方と共存しませんので、新しい書き方を学ぶべきです

```js
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
```

上記の2つの要素は、Reactの観点から見れば全く同等な機能を提供しあmす。クラスに関しては、[こっち](https://facebook.github.io/react/docs/state-and-lifecycle.html)で説明されているいくつかの追加機能があり、ここで詳しく説明されているので。ここでは、機能部品を簡潔に使用します。

# コンポーネントのレンダリング

以前は、DOMタグを表すReact要素のみに遭遇しましたが、

```js
const element = <div />;
```

ただし、要素はユーザー定義のコンポーネントを表すこともできます。

```js
const element = <Welcome name="Sara" />;
```
Reactは、ユーザ定義のコンポーネントを表す要素を見ると、JSX属性を単一のオブジェクトとしてこのコンポーネントに渡します。このオブジェクトを「props」と呼びます。たとえば、次のコードでは、ページに「Hello、Sara」と表示されます。

```js
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);
```

[CodePen](http://codepen.io/gaearon/pen/YGYmEG?editors=0010)で試してみてください。


# 上記の例で何が起こっているのか見てみましょう

まず`ReactDOM.render()`で`<Welcome name="Sara" />` エレメントを呼んでいます。次に`Welcome`コンポーネントでは`{name: 'Sara'}`の値を参照しています。`Welcome`コンポーネントは結果として`<h1> Hello、Sara </ h1>`エレメント（要素）を返します。React DOMは効率的に`<h1>Hello, Sara</h1>`DOMを更新して一致させます

```
注意点：

コンポーネント名は常に大文字で開始してください。
たとえば、<div />はDOMタグを表しますが、<Welcome />はコンポーネントを表し、
ウェルカムをスコープに入れる必要があります。
```

# コンポーネントの作成


コンポーネントは、他のコンポーネントを参照できます。これにより、どの階層に位置するコンポーネントに対しても同じコンポーネントの抽象化を表現できます。ボタン、フォーム、ダイアログ、スクリーン：Reactアプリケーションでは、すべてがコンポーネントとして一般的に表現されます。たとえば、`Welcom`を何度もレンダリングする`App`コンポーネントを作成できます。

```js

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      //ここ
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

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


[CodePen](http://codepen.io/gaearon/pen/KgQKPr?editors=0010)で試してみてください。


通常、新しいReactアプリケーションには、一番上に1つのコンポーネントがあります。しかし、Reactを既存のアプリケーションに統合する場合、Buttonのような小さなコンポーネントでボトムアップを開始し、徐々にビュー階層の最上位に向かって作業を進めることができます。

```
注意：
コンポーネントは単一のルート要素を返す必要があるので、すべての<Welcome />要素を含むように<div>を追加しています
```

# コンポーネントの抽出

たとえば、下記のようなコンポーネントを考えてみましょう。

```js
function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}
```
[CodePen](http://codepen.io/gaearon/pen/VKQwEo?editors=0010)で試してみてください。


# 大きなコンポーネントを小さなコンポーネントに分割するのを恐れない

### 全ソース

```js
function formatDate(date) {
  return date.toLocaleDateString();
}

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
             src={props.author.avatarUrl}
             alt={props.author.name} />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

const comment = {
  date: new Date(),
  text: 'I hope you enjoy learning React!',
  author: {
    name: 'Hello Kitty',
    avatarUrl: 'http://placekitten.com/g/64/64'
  }
};


ReactDOM.render(
  <Comment
    date={comment.date}
    text={comment.text}
    author={comment.author} />,
  document.getElementById('root')
);

```

上記のコードでは`author`（オブジェクト）、` text`（文字列）、 `date`（日付）をpropsとして受け取り、ソーシャルメディアのWebサイトにコメントを記述します。このコンポーネントは、すべてがネストされているため変更するのが難しく、個々の部分を再利用することも困難です。そこからいくつかのコンポーネントを抽出しましょう。まず、「アバター」を抽出します。

```js
function Avatar(props) {
  return (

    //ここ
    <img className="Avatar"
      src={props.user.avatarUrl}
      alt={props.user.name}
    />
　　//ここ

  );
}
```

`Avatar`は` Comment`の中でレンダリングされていることを知る必要はありません。その支柱に `author`ではなく` user`というより一般的な名前を与えたのはそのためです。

```js
function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        //ここ
        <Avatar user={props.author} />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}
```


次に、ユーザーの名前の横にアバターを描画するUserInfoコンポーネントを抽出します。

```js

function UserInfo(props) {
  return (
    //ここ
    <div className="UserInfo">
      <Avatar user={props.user} />
      <div className="UserInfo-name">
        {props.user.name}
      </div>
    </div>
　　//ここ
  );
}

```

これにより、さらに単純化することができます。

```js
function Comment(props) {
  return (
    <div className="Comment">
      //ここ
      <UserInfo user={props.author} />
　　　//ここ
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}
```

[CodePen](http://codepen.io/gaearon/pen/rrJNJY?editors=0010)で試してみてください。


コンポーネントの抽出は、最初は面倒な作業のように思えるかもしれませんが、再利用可能なコンポーネントのパレットを持つことは、より大きなアプリケーションを実現するときに役に立ちます。再利用可能なコンポーネントを創造することを意識しましょう。

# 参考

[React.jsでComponentの分割をしてみる](http://off.tokyo/blog/2017/04/29/react-js%E3%81%A7component%E3%81%AE%E5%88%86%E5%89%B2%E3%82%92%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B/)