Reactで挨拶


この記事は社内勉強会用として作られました。
[Pro React](http://www.pro-react.com/)という本を読みながら進みます。

本の内容と異なる部分

* 本のサンプルをESlintとAirbnbのスタイルガイドに合わせて直しました。
* create-react-appを用いてプロジェクトを生成しました。
* node.jsを含めてreactとreact-dom、そして本で紹介されたライブラリーを最新バージョン（2017.6.18）に合わせて直しました。

本のサンプルは[ここ](https://github.com/pro-react)で確認してください。

## Vimの設定

開発ツールとしてVimを使います。
下記のファイルでVimの環境設定を行なってください。
ここではReactを学ぶことが目的なので、Vimの説明はしません。

```sh
% cd ~
% git clone https://gitlab.com/devtopia/dotfiles.git
% ln -sf dotfiles/.vim .vim
% ln -sf dotfiles/.vimrc .vimrc
% ln -sf dotfiles/.eslintrc .eslintrc
% ln -sf dotfiles/.tern-project .tern-project

# Vimの設定ファイルからフラグインをインストール
% vim .vimrc
:PlugInstall!
```

rubyとjavascriptの場合は__rubocop__と__eslint__のスタイルガイドを適用しています。
rubocopとeslintが先に設置されている必要があります。
gemとnpm（またはyarn）でそれぞれ設置してください。
xcodeが設置されてない方は次のコマンドで設置してください。

```sh
% sudo xcode-select --install
```

\:bulb: 自分が直接設定したい場合は[VimでReactの開発を楽々](http://qiita.com/park-jh/items/b353319efb1823c36c05)という記事を参考にしてください。

## 関連記事

* [Reactのスタート](http://qiita.com/park-jh/items/63bf0f013c998c5572aa)
* [Reactのプロジェクト](http://qiita.com/park-jh/items/488d43e2d0b87991207e)
* Reactで挨拶
* [ReactでTrelloみたいなToDoリスト＜1＞ props](http://qiita.com/park-jh/items/f3f6162cee982eb9e6f3)
* [ReactでTrelloみたいなToDoリスト＜2＞ state](http://qiita.com/park-jh/items/0b71fd9c7e6cc8cbe844)
* [ReactでTrelloみたいなToDoリスト＜3＞ prop-types](http://qiita.com/park-jh/items/6a8eac233e3f3ae61f32)
* [ReactでTrelloみたいなToDoリスト＜4＞ immutability-helper](http://qiita.com/park-jh/items/6166434f80bc186f8c77)

## 第一歩、挨拶

```diff:src/components/Hello.js
diff --git a/src/components/Hello.js b/src/components/Hello.js
new file mode 100644
index 0000000..1dc66a9
--- /dev/null
+++ b/src/components/Hello.js
@@ -0,0 +1,11 @@
+import React from 'react';
+
+class Hello extends React.Component {
+  render() {
+    return (
+      <h1>Hello World</h1>
+    );
+  }
+}
+
+export default Hello;
```

```diff:src/index.js
diff --git a/src/index.js b/src/index.js
index 53c7688..219b78a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,8 +1,8 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
-import App from './App';
+import Hello from './components/Hello';
 import registerServiceWorker from './registerServiceWorker';
 import './index.css';

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

\:bulb: stateless componentとは
<details>
Reactのcomponentはstateful componentとstateless componentで分けられる。
stateless componentとはその名の通り状態を持ってないcomponentを言う。
ここではとりあえずrender()だけを持ってるcomponentだと考えても構わない。
状態を持ってないcomponentについてはfunctionやarrowを使うのが推奨されていて、class式を使うとeslintからエラーが出る。
</details>

* functionを使う場合、class式よりシンプルになる。

```javascript:src/components/Hello.js
import React from 'react';

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

export default Hello;
```

* arrow関数を使うともっとシンプルになる。

```javascript:src/components/Hello.js
import React from 'react';

const Hello = () => <h1>Hello World</h1>;

export default Hello;
```

javascriptの理解度によって異なるが、慣れていない人にはclass式がわかりやすいと思う。
ここではeslintのruleでstateless function部分をdisableした。

## Destructuring assignment（分割代入）

```diff:src/components/Hello.js
diff --git a/src/components/Hello.js b/src/components/Hello.js
index 1dc66a9..bae48e4 100644
--- a/src/components/Hello.js
+++ b/src/components/Hello.js
@@ -1,6 +1,6 @@
-import React from 'react';
+import React, { Component } from 'react';

-class Hello extends React.Component {
+class Hello extends Component {
   render() {
     return (
       <h1>Hello World</h1>
```

## Dynamic Values

```diff:src/components/Hello.js
diff --git a/src/components/Hello.js b/src/components/Hello.js
index bae48e4..66b65fc 100644
--- a/src/components/Hello.js
+++ b/src/components/Hello.js
@@ -2,8 +2,9 @@ import React, { Component } from 'react';

 class Hello extends Component {
   render() {
+    const place = 'World';
     return (
-      <h1>Hello World</h1>
+      <h1>Hello {place}</h1>
     );
   }
 }
```

\:bulb: var、let、constについて
<details>
\:point_right: var
グローバルとローカルのscopeを区分するために使っていた。
同じ変数名でも重複で宣言できる。
ES6ではletやconstを使う。原則varは使わない。
\:point_right: let
変数を宣言する場合に使う。
同じ変数名で重複宣言はできない。エラーになる。
\:point_right: const
値が変わらない場合に使う。
数値や文字列を代入する時使うことだと勘違いしやすいが、class式を使ったオブジェクトについてもconstantだど読んでいる。
（案外使う場合が多いということだ。）
</details>

## Composing Components（props）

Reactのコンポーネント間受け渡しには２種類がある。

* __props__
* state

stateについては後で扱う予定だ。
ここではpropsについて簡単に触れてみよう。

### props（properties）

propsはコンポーネントの構成情報である。
親コンポーネントから子コンポーネントへデータ（props）を渡すときに使う。
親から子への一方通行で子コンポーネントから値の変更はできない。

```diff:src/components/GroceryList.js
diff --git a/src/components/GroceryList.js b/src/components/GroceryList.js
new file mode 100644
index 0000000..6fe4c05
--- /dev/null
+++ b/src/components/GroceryList.js
@@ -0,0 +1,16 @@
+import React, { Component } from 'react';
+import ListItem from './ListItem';
+
+class GroceryList extends Component {
+  render() {
+    return (
+      <ul>
+        <ListItem quantity="1" name="Bread" />
+        <ListItem quantity="6" name="Eggs" />
+        <ListItem quantity="2" name="Milk" />
+      </ul>
+    );
+  }
+}
+
+export default GroceryList;
```

```diff:src/components/ListItem.js
diff --git a/src/components/ListItem.js b/src/components/ListItem.js
new file mode 100644
index 0000000..8285ebc
--- /dev/null
+++ b/src/components/ListItem.js
@@ -0,0 +1,11 @@
+import React, { Component } from 'react';
+
+class ListItem extends Component {
+  render() {
+    return (
+      <li>{this.props.quantity} x {this.props.name}</li>
+    );
+  }
+}
+
+export default ListItem;
```

```diff:src/index.js
diff --git a/src/index.js b/src/index.js
index 219b78a..d690d95 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,8 +1,8 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
-import Hello from './components/Hello';
+import GroceryList from './components/GroceryList';
 import registerServiceWorker from './registerServiceWorker';
 import './index.css';

-ReactDOM.render(<Hello />, document.getElementById('root'));
+ReactDOM.render(<GroceryList />, document.getElementById('root'));
 registerServiceWorker();
```

### props.children

```diff:src/components/GroceryList.js
diff --git a/src/components/GroceryList.js b/src/components/GroceryList.js
index 6fe4c05..9a419b3 100644
--- a/src/components/GroceryList.js
+++ b/src/components/GroceryList.js
@@ -5,9 +5,9 @@ class GroceryList extends Component {
   render() {
     return (
       <ul>
-        <ListItem quantity="1" name="Bread" />
-        <ListItem quantity="6" name="Eggs" />
-        <ListItem quantity="2" name="Milk" />
+        <ListItem quantity="1">Bread</ListItem>
+        <ListItem quantity="6">Eggs</ListItem>
+        <ListItem quantity="2">Milk</ListItem>
       </ul>
     );
   }
```

```diff:src/components/ListItem.js
diff --git a/src/components/ListItem.js b/src/components/ListItem.js
index 8285ebc..f3904bb 100644
--- a/src/components/ListItem.js
+++ b/src/components/ListItem.js
@@ -1,11 +1,17 @@
 import React, { Component } from 'react';

 class ListItem extends Component {
   render() {
     return (
-      <li>{this.props.quantity} x {this.props.name}</li>
+      <li>{this.props.quantity} x {this.props.children}</li>
     );
   }
 }

 export default ListItem;
```