(イマドキの)手探りReact.js入門記

[手探りVue.js入門記](https://qiita.com/kznr_luk/items/d8ea31760061fbbdfc45)もどうそ。
同じようにノートとして使いつつ色々まとめていきます。追記予定。

## 自分以外の見る人へ
何番煎じの入門記事なんだと思う方もいるかもしれませんが、当記事では古今東西すべてのインターネット上のReact.jsのコードを**今風に脳内で変換できるようになるまでに必要だった情報**を重点的にまとめています。React.jsは今と昔で全然書き方が違うばかりか、何も考えず今風の書き方に脳内変換すると動かなかったりします。

ここのコードは下記のような環境で書かれています。

- 記述にはVisualStudio Codeを使用
- React.js / React-DOM.js / ~~JSXTranceFormer.js~~ Babel.js はCDNから取得(npm install等は使っていない)

要は一番手軽なReact.jsの始め方になります。

## より詳しい入門記事を紹介
- [ES6版React.jsチュートリアル - Qiita](https://qiita.com/nownabe/items/2d8b92d95186c3941de0#%E6%9C%80%E5%88%9D%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%82%92%E4%BD%9C%E3%82%8B)
今風の書き方で紹介されています。npmで環境構築をしているようです。

では。

## 実際に始める前に
React.jsを試すのにnpmで環境構築や雛形の生成はしたくない。その為CDNを使用することにした。
すでにここからReact.jsのバージョンによる差異が出てきている。

**昔:**  読み込むべきはReact.jsと**JSXTranceFormer.js**
**今:**  読み込むべきはReact.jsと**ReactDOM.js**と**Babel.js**

**React.js**
=> 言わずもがな、React.js本体。必須。
**ReactDOM.js**
=> React.js 0.1.14~ はDOM操作に関する部分は分割された。クライアントサイドで描写するなら必須。
**Babel.js**
=> React.jsで利用されているHTMLの記法**JSX**を、内部的にJavaScriptに変換するために必須。
=> 以前はこの役割を[JSXTranceFormer.jsが請け負っていた。](https://reactjs.org/blog/2015/06/12/deprecating-jstransform-and-react-tools.html)HTML内のコメントを参照。

```html:index.html
<!DOCTYPE html>
<html>
<head>
  <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
</head>
<body>
  <div id="main"></div>
  <!-- 古いコードでは下記typeの部分が"text/jsx"になっている -->
  <script type="text/babel" src="js/script.js"></script>
</body>
```
***今後のJavaScriptコードはすべてこのHTMLを使用している。***

## React.jsについて
先日はVue.jsを試したが、本当にやりたいのはReact.jsだったので手をつけ始める。
React.jsはVue.jsとは違い、HTMLの表現に**"JSX"**を使っているのが大きな特徴で、それ以外は素のJavaScriptのような見た目をしている。今回はReact.jsそのもののメリットやデメリットについては触れない。

```scala:react_sample.js
// 今風の書き方。下で解説。ちなみにこのclass一塊をReact.jsではコンポーネントと言う。
class Hello extends React.Component {
    render() {
        // JSXでレンダリングすべき要素を返す。
        return (<h1>Hello React.js</h1>);
    }
}
// 実際にレンダリングする部分。Class HelloをHTML内のid='main'内にレンダリングせよ、という命令。
ReactDOM.render(
    <Hello />,
    document.getElementById('main')
)
```


## 今風の書き方

- ``var HelloWorld = React.createClass{~~}``はもう使わない。代わりに``class``を使う。
- 自作メソッドを使うときは``constructor(props)``内でメソッドと``this.``をバインドしなければならない。
- stateの初期化にもはや``getInitialState()``は使わない。

### ``var HelloWorld = React.createClass{~~}``はもう使わない。代わりに``class``を使う。
``var HelloWorld = React.createClass{~~}``と書き始めていたが、今はReact.Componentを継承して新しいクラスを作るのが良いらしい。ES6的書き方に慣れていればこっちのがわかりやすい。

```scala:今風の書き方
class HelloWorld extends React.Component {
    render(){
        // QiitaはJSXに対応していないので、おそらくh1がハイライトされている。が、問題なし。
        return (<h1>Hello World</h1>)
    }
}
```
ちなみに、以前のReact.createClass{~~}も今しばらくは使用できる。違いについてはこの記事が詳しかった。ES6以降の書き方をするのであれば、``React.Component``を使用するのが良さそうだ。

[ES5のReact.jsソースをES6ベースに書き換える - Qiita](https://qiita.com/kuniken/items/2e850daa26a10b5098d6#reactcreateclass-vs-extends-reactcomponent)

最後に同じ挙動をするコードの比較を書いておく。

```scala
// これは古い書き方
var HelloWorld = React.createClass({
    render: function() {
        return (
            <div className="hw">
                Hello World.
            </div>
        );
    }
});
```

多くの場合は下のようにメソッド定義時の無名関数の書き方が変わるだけで済む。もともとES6を書いていた人は脳内変換が簡単ではないかと思う。

```scala
// 新しい書き方
class HelloWorld extends React.Component{
    render(){ // function()がなくなり、ES6と同じメソッド的書き方になっている。
        return (
            <div className="hw">
                Hello World.
            </div>
        );
    }
}
```

### 自作メソッドを使うときは``constructor(props)``内でメソッドと``this.``をバインドしなければならない。
これは、コードの中で``this.``というワードを使用するときには必ず行わなければならない。

例えば、**自身で新しいメソッドを定義する場合。** インターネット上で見つけた情報をES6的書き方にしているだけなのに動かない、ということがよくある。
下は、ボタンを追加し、押されたときに何らかの処理をしたい場合の例。動かない例では、ButtonOnClickなんてメソッドは無いと怒られる。

```scala
// 動かない。
class HelloWorld extends React.Component{
    ButtonOnClick(){
        /**
         * ボタンが押されたときの処理
        **/
    }
    render(){
        return (
            <div className="hw">
                Hello World.
                <Button onClick={this.ButtonOnClick}>CLICK!</Button>
            </div>
        );
    }
}
```

これは、classを継承した時点ではthisが初期化されていないため。詳しいことは[こちらの記事](http://js-next.hatenablog.com/entry/2014/11/01/034607)にかかれている。
そのため、まず``constructor()``内で``super();``を呼び出し、thisを初期化後、そのthisをメソッドにバインドするという一連の作業が必要である。(追記予定)

```scala
// 動く。
class HelloWorld extends React.Component{
    // ここに注目
    constructor(props) {
        super(props);
        this.ButtonOnClick = this.ButtonOnClick.bind(this);
    }

    ButtonOnClick(){
        /**
         * ボタンが押されたときの処理
        **/
    }
    render(){
        //             同上
    }
}
```

### stateの初期化にもはや``getInitialState()``は使わない。
これもハマったポイントの一つ。``getInitialState()``メゾットを書く必要はなく、``constructor()``内でそのまま代入すればよい。

```scala
class Contents extends React.Component {
    constructor(props) {
        super(props);
        this.state = { ID: 0, result: {}, value : '' };
    }
    render(){
        //             同上
    }
}
```
ただし```this.setState();```は健在。値を変更する時に```this.state```に直接代入してはいけない。

## あとがき

自身も初学者なので、何かここ違うよという指摘がありましたらコメントしていただけると幸いです。よろしくお願いします。