React.jsチートシート

## 概要
React = Facebook社が公開したUI構築のためのjsライブラリ

- コンポーネントという単位で、UIごとに機能を宣言的に実装する

- MVC/MVVMでいうところのView/View-modelのみを担当する
    - その他の部分はRedux/Fluxを組み合わせて構築する例が多い模様

- HTMLのDOMを直接操作せず、Virtual DOM に対して操作を行う
    - Virtual DOMからHTML DOMへの反映はReactが効率的に行ってくれる

- jQueryと併用__できる__
- Bootstrapのような、UIのデザインライブラリとしての機能は__持たない__


## 導入
npmあるいはCDNで導入できる。

```console:npm
$ npm install react
$ npm install react-dom
```

```html:CDN
<script src="https://unpkg.com/react@15/dist/react.min.js"></script>
<script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script>
```

### JSXの利用の有無

JSX = js内にXML風のマークアップを埋め込む記法。

- JSXなしでもReactは利用できる(表記方法が通常のjsになる)
- JSXを使う場合は、XML風の表記に加えてES6の構文が利用できる(harmony)

JSXを使う場合はいずれかの方法で運用する:

#### 実行時に変換用のスクリプトを読み込み、変換する


JSXTransformer.js を使う。
この方法は読み込みのつど変換がかかるので、パフォーマンスは悪い(開発用)。


```html
<script src="http://fb.me/JSXTransformer-0.12.1.js"></script>
<script type="text/jsx;harmony=true">
    // JSX表記が可能となる
</script>
```

非推奨になった模様。
[変わりにBabelを使う方法が紹介されていた。](https://utano.jp/entry/2016/07/react-js-load-from-cdn/)

```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
<script type="text/babel">
</script>
```


#### ビルド時にjsファイルをコンパイルする

react-toolsを使う。

```console
# グローバルにreact-toolsをインストールする
# jsxコマンドが使えるようになる
$ npm install -g react-tools

# コンパイル
$ jsx --harmony path/to/src/ path/to/dest/
```

その他、ビルドツールやタスクランナーと組み合わせてコンパイルすることも可能な模様。



## 機能

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

#### 定義する
- コンポーネントは、 
    - ES5の場合、`React.createClass()` に対してオブジェクトを渡すことで生成する
    - ES6の場合、`React.Component`クラスを継承したクラスを定義する

- パラメータとなるオブジェクトには、最低限`render()` メソッドが必要となる
- `render()` の戻り値は、コンポーネントオブジェクト(JSX)であること

```jsx
// ES5表記
var Foo = React.createClass({
    render(){
        return (<div>Foo</div>);
   },
});

// ES6表記
class Foo extends React.Component{
  render(){
        return (<div>Foo</div>);
   }
});
```

#### 入れ子にする

コンポーネント内に別のコンポーネントを含めることができる。

```jsx
class Foo extends React.Component{
    render(){
        return (<div>Foo!</div>);
   }
}

class Bar extends React.Component{
    render(){
        return (<div><Foo /> Bar!</div>);
   }
}
```

#### レンダリング(DOMに出力)する

`ReactDOM.render()` でコンポーネントをDOMにレンダリングできる。

```jsx
ReactDOM.render(
    <Foo />,           // 出力するコンポーネントを指定
    $('#target')[0]    // 出力先のelementを指定(jQueryを併用できる)
);
```

#### 関数でコンポーネントを定義する

関数コンポーネント = 関数表記(function)により定義されたコンポーネント。
状態制御やクラス構造が不要な場合、関数コンポーネントを使うことで定義を省略できる。

```jsx
// 関数コンポーネントを定義
// propsは引数として渡す
function Baz(props){
    return (<div>Baz {props.msg}</div>);
}

// クラス定義したコンポーネントと同様に使える
ReactDOM.render(
  <Baz msg={'message through props'}/>,
  $('#sandbox')[0]
);
```


### パラメータ(props)

propsは、コンポーネントの内外でパラメータをやりとりする仕組み。

#### propsを渡す

コンポーネントをレンダリングする際に、属性として変数を渡せる。

```jsx:レンダリング時に渡す
ReactDOM.render(
    // Fooコンポーネントにパラメータmsgとnumを渡す
    <Foo msg="abc" num=123/>,
    $('#sandbox')[0]
);
```

```jsx:コンポーネントを入れ子に定義する際に渡す
class Bar extends React.Component{
    render(){
        // 同じくFooコンポーネントにパラメータを渡す
        return(<div><Foo msg="xyz" num=999 /> Bar!</div>);
   }
}
```

#### propsを参照する

渡されたpropsは、`this.props`オブジェクトによって参照できる。

```jsx:渡されたパラメータmsgとnumを参照する
class Foo extends React.Component{
    render(){
        return (<div>
            <div>Foo!</div>
            <div>message = {this.props.msg}</div>
            <div>num = {this.props.num}</div>
        </div>)
    }
}
```

#### 式展開する

propsにかぎらず、JSXオブジェクト内に中括弧 `{ }` で式を囲むことで、その評価値をレンダリングできる。

```jsx:props以外も展開できる
class Foo extends React.Component{
    render(){
        return (<div>
            <div>Foo!</div>
            <div>message = {'ふがふが'}</div>
            <div>num = {SOME_CONSTANT}</div>
        </div>)
    }
}
```

#### コンポーネントを動的に構築する

JSXで定義したコンポーネントオブジェクトは、任意に変数に格納できる。
またそれを別のJSX内で展開できる。


```jsx
function FooList(props){
    // 変数に格納
    const foo = (<Foo />);

    // 配列に格納
    let foos = [];
    for(let i=0; i < props.length; i++)
        foos.push(foo);

    // 展開
    return (<div>{foos}</div>);
}

ReactDOM.render(
  <FooList length=3 />,
  $('#sandbox')[0]
);

```


### イベント

#### イベントを設定する

コンポーネントのイベントは、JSX内のイベント属性に、無名関数を渡すことで定義する。

```jsx:クリック時にアラートを表示する無名関数を設定
class Foo extends React.Component{
    render(){
        return (<div onClick={function(){ alert('clicked'); }}>
            Foo!
        </div>)
    }
}
```

また無名関数には、ES6の[アロー関数](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/arrow_functions)を使うことができる。

```jsx:アロー関数をイベントに設定
class Foo extends React.Component{
    render(){
        return (<div onClick={() => alert('clicked') }>
            Foo!
        </div>)
    }
}
```

関数オブジェクトを渡せばいいので、メソッドや通常の関数でも可。

```jsx:インスタンスメソッドをイベントに設定
class Foo extends React.Component{
    onClick(){
        alert('clicked');
    }

    render(){
        // この書き方でも動くが、メソッド内のthisがundefinedになる
        //return (<div onClick={this.onClick}>

        return (<div onClick={() => this.onClick() }>
            Foo!
        </div>)
    }
}
```

#### 移譲する(delegateパターン)

上位のコンポーネントにイベントを移譲したい場合は、`props`にイベントを設定する方法で対応できる。

```jsx:propsを介したデリゲーション
class Foo extends React.Component{
    render(){
        return (
            <button className="square" onClick={this.props.onClick }>
                Foo
            </button>
        );
    }
}

class Bar extends React.Component{
    onClick(){
        alert('clicked');
    }

    render(){
        // クリックイベントをpropsとして渡す
        return (<div>
            Bar!
            <Foo onClick={() => this.onClick() }/>
        </div>);
    }
}
```

### 状態制御

コンポーネントの状態は、インスタンス変数`state`で保持する。
stateはコンストラクタ内で定義する。

```js:コンストラクタとstateを定義する
class Foo extends React.Component{
    constructor(){
        super();

        this.state = {
            activated: false,
            clicked: true,
        };
    }
    // ...
}
```

stateを変更する際には、`setState()` を介して設定する。
こうするとコンポーネントの定義内(JSX)でstateを参照している場合に、__再レンダリング__がかかる。


```jsx:クリック状態によって表示を更新する
class Foo extends React.Component{
    constructor(){
        super();
        this.state = {
            count: 0,
        };
    }

    onClick(){
        // クリックするたびに表示される数字を増やす
        this.setState({
            count: (this.state.count+1),
        });
    }

    render(){
        return (<div onClick={() => onClick() }>
            {this.state.count}
        </div>)
    }
}
```

### key
key = 連続する要素を識別するための名前のこと。
リスト構造の要素に対してkeyを指定することで、それらの要素が非効率に再レンダリングされることを防ぐ。

```jsx:keyを指定する
class Bar extends React.Component{
    constructor(){
        super();
        this.state = {
            count: 0,
        };
    }

    onClick(){
        // クリックされるたびに、カウントを増やしてFooの数を増やす
        this.setState({count: this.state.count+1});
    }

    render(){
        // 繰り返しになるFooにkeyを指定して、レンダリング効率を向上させる
        let foos = [];
        for(let i=0; i < this.state.count; i++)
            foos.push(<li><Foo key={i} /></li>);

        return (<div onClick={()=> this.onClick() }>
            Bar! <ul>{foos}</ul>
        </div>);
    }
}
```

keyはpropsと同じ記法で定義するが、`this.props.key`として参照することは__できない__。


### refs

- ref = コンポーネント内の要素に対して任意につけられる名前のこと
- refs = コンポーネント内で定義されたrefの一覧を保持するプロパティ

```jsx:refsで要素を指定して操作する
class Foo extends React.Component{
    constructor(){
        super();
    }

    onClick(){
        // ref=alphaの要素を取得・操作する
        let alpha = this.refs.alpha;                // React backing instance
        let alphaDOM = ReactDOM.findDOMNode(alpha); // HTML Elem
        let $alpha = $(alphaDOM);                   // jQuery obj
        $alpha.html('ALPHA');
    }

    render(){
        // 2つのdivにそれぞれ違うrefを付ける
        return (<div onClick={()=> this.onClick() } >
            Foo!
            <div ref="alpha">alpha</div>
            <div ref="bravo">bravo</div>
        </div>);
    }
}
```

### ライフサイクルイベント

規定の名前のメソッドをコンポーネントに定義しておくと、コンポーネントの状態が変わった際にそれらが自動的に呼ばれる(= ライフサイクルイベント)。

`constructor()`や`render()` もライフサイクルイベントのひとつ。

```js:実装例
class Foo extends React.Component{
    componentWillMount(){
        // ...
    }
}
```

#### 一覧

引数/戻り値など詳細は[公式のリファレンス](https://facebook.github.io/react/docs/react-component.html)を参照のこと

分類                                | メソッド                      | タイミング
---                                 | ---                           | ---
Mounting(DOMへの追加時)             | constructor()                 | コンポーネントのマウント(DOMへの追加)前
                                    | componentWillMount()          | マウント前
                                    | render()                      | マウント時
                                    | componentDidMount()           | マウント後
Updating(コンポーネントの更新時)    | componentWillReceiveProps()   | setProps()によるプロパティの更新時
                                    | shouldComponentUpdate()       | stateかpropsの変更による更新の可否の問合せ
                                    | componentWillUpdate()         | 更新前
                                    | render()                      | 更新時
                                    | componentDidUpdate()          | 更新後
Unmounting(DOMからの削除時)         | componentWillUnmount()        | アンマウント(DOMからの削除)時



## 参考
- [これからReact.js勉強するかたにオススメな記事13選](http://ichimaruni-design.com/2016/03/reactjs-13/)
- [npmを使わずにReactの開発環境を構築する方法（CDNで配信されているReactとbabel-coreを利用）](https://utano.jp/entry/2016/07/react-js-load-from-cdn/)
- [Github - facebook/react](https://github.com/facebook/react)
- [Tutorial: Intro To React](https://facebook.github.io/react/tutorial/tutorial.html)
- [Refs to Components](http://reactjs.cn/react/docs/more-about-refs.html)
- [React.Component](https://facebook.github.io/react/docs/react-component.html)

- [Qiita - 5分で理解する React.js](http://qiita.com/tomzoh/items/7fabe7cb57dd96425867)
- [Qiita - 一人React.js Advent Calendar 2014](http://qiita.com/advent-calendar/2014/reactjs)
- [Qiita - 今からはじめるReact.js〜propsとstate、それからrefs〜](http://qiita.com/kuniken/items/a22adda392ccc30011b1)
- [js Studio - React入門](http://js.studio-kingdom.com/react/guides/getting_started)