Reactの個人的な忘備録


画面の部品（Component）ごとに状態を管理するフレームワーク。

![Untitled Diagram (3).png](https://qiita-image-store.s3.amazonaws.com/0/287848/cca433c5-0eaf-4480-4abf-30224c7cc6a9.png)
※reactとセットで扱われることの多いflux準拠の構造を示す図でなく、
  reactの機能のみに着目した図


#### メリット
1.  直観的なビューコードの記述
1.  責任の分離・カプセル化

#### デメリット
1.  バージョンアップで記法の変化が多め
    (node.jsみたいにLTS版ほしいですね）
1. 描画コードに実行時エラーがあると、HTMLと違ってエラー部以外が
  描画されたりしないのでエラー原因がわかりにくい。





### **直観的なビューコードの記述**
HTMLの要領で動的UIを定義できるので、
jQuery等でDOMの要素を検索 → 更新後の要素に差替という操作が不要になる。

例）
1. React.Component（画面部品の基底）を継承したクラスを作成
2. render()メソッドをオーバーライドし、DOMテンプレートを返す（※）
※javascript内にHTMLを記述する形式は糖衣構文。
コンパイルでDOMを生成するjavascriptに変換する。

```jsx:
class Home extends React.Component {
  constructor(props) {
    super(props);
    this.state = { inputValue: ''};
    this.onChangeInput = this.onChangeInput.bind(this);
    this.onClickBtn = this.onClickBtn.bind(this);
  }

  // 描画
  render(){
      // DOMのテンプレートを作成し、動的な部分は{}内に記述する
      return (
      <div style={{flex:1, flexDirection:"column"}}>
        <div style={{fontWeight:"bold"}}>Title</div>
        <div>
          <input onChange={this.onChangeInput}/></div>
        <div>
          <button onClick={this.onClickBtn}>Show</button>
        </div>
        <div>
          <label>{this.state.inputValue}</label>
        </div>
      </div>
    );  
  }
  
  // 入力値を保存
  onChangeInput(e){
    // 本来stateの値は直接編集すべきではない
    // (this.setState()でキーを指定して編集する）
    // (ここではわざとボタンを押すまで再レンダリングしないようにしている）
    this.state.inputValue = e.target.value;
  }

  // 保存した入力値でrenderを再描画
  onClickBtn(){
    this.setState({inputValue: this.state.inputValue});
  }
}
```

実行結果　↓

![名称未定-22.jpg](:storage\8c5e20fb-f0ce-4cce-bb1b-9263f83e3f04\04fdb3f5.jpg)
**show**ボタンを押すと入力欄の内容が下部ラベルに表示される。


### **責任の分離・カプセル化**
コンポーネント（部品）単位の閉じた世界で入出力、イベントを定義する。
画面部品ごとにDOMを記述するので、対象外の要素を編集する危険性がなくなる。
(例えばjQueryで「$(".className")」で、意図しない要素を
取得し、編集してしまうなど)

また、最近増加しているSPA(SinglePageApplication)では
画面部品を切替・画面を部品単位に表示更新などが必要になる。
その単位とクラスを一致させることができ、クラス設計を単純化できる。
（ReactRouterによる管理で、ブラウザの戻る進むにも対応できる）



## ハマりポイント
### ReactRouter 
v3とv4で記法が大きく異なる。

- react-routerを利用
- Routerに対して属性（ここではhashHistory)を設定する。
- ルーティング構造はネスト形式で表現する。

```jsx:v3
import { Router, Route, hashHistory } from "react-router";
const routing = (
  <Router history={hashHistory}>
    <Route path='/' component={App}>
      <Route path='menu' component={Menu} />
     // ...
    </Route>
  </Router>
)
```

- react-router-domを利用
- 目的に応じたルーター(ここではHashRouter)を設定する
- Router直下の要素は1つとし、階層構造はパスで示す
- 
```jsx:v4
import {Route, HashRouter} from "react-router-dom";
const routing = (
  <HashRouter>
    <div>
      <Route path='/' component={App} />
      <Route path='/menu' component={Menu} />
     // ...
    </div>
  </HashRouter>
)
```

### ReactComponentの読込順
ReactRouterで参照するcomponentのクラスは、先に読み込まれている必要がある。
後方で読み込まれた場合、**エラーにならないが、何もレンダリングされない**という状態になる。

### ES6(クラス）形式のReactComponentのイベントハンドラ
[公式Handling Events – React](https://reactjs.org/docs/handling-events.html)
コンストラクタでイベントハンドラをバインドしないと
イベントハンドラでthisがundefinedになる。

```jsx
class Home extends React.Component {
  constructor(props) {
    super(props);
    // ここでthisをバインドしないと
    this.onChangeInput = this.onChangeInput.bind(this);
  }
  
  onChangeInput(e){
    // ここでthisがundefinedになる
    // ⇒ハンドラを呼び出すのはReactのフレームワークのため
    this.setState({inputValue: e.target.value});
  }
  
  render(){
      return (<div><input onChange={this.onChangeInput}/></div>);  
}
```

### Renderメソッド内でのラムダ関数
Renderメソッド内でラムダ関数を定義するのはパフォーマンス上よろしくない。
⇒再描画されるたび関数の生成が行われるため。

### StateとProps
React.Componentのメンバstateとpropsの扱い
- state … ビューモデル(UIに依存しないものはstateに含めない)
- props …親コンポーネントのstateや、URLパラメータの情報（参照のみの情報） 


### ReactComponentメソッドの呼ばれるタイミング

|メソッド|タイミング|
|---|---|
|constructor|コンポーネント作成時|
|render|DOMマウント時|
|componentDidMount|DOMマウントされた後 1回だけ|
|getDerivedStateFromProps|state、props変更前 static(引数:変更前state、変更後props)|
|componentDidUpdate|state、props変更後|
|shouldComponentUpdate|再レンダリング前 再レンダリング要否を返す|
|getSnapshotBeforeUpdate|再レンダリング前|
|componentWillUnmount|DOMアンマウントされる前|
|componentWillMount|**廃止予定** |
|componentWillUpdate|**廃止予定** |
|componentWillRecieveProps|**廃止予定** |

### 気になるところ
・jsx（Reactコンポーネント）の中でstyle属性を記述するインラインスタイルの記法は
　デザインとコードの分離ができなくなるのでは？
　⇒公式非推奨のようなので気にしないようにしよう。
　　https://reactjs.org/docs/dom-elements.html#style