[React] 用語集

# はじめに
[React チュートリアル - Qiita](https://qiita.com/o_sol06/items/dce7b6c99ecb3abf7ec1)をやっていて分からなかった単語など調べてみました。
propsとstatusの違いは最初混乱したため、気持ち丁寧に記載しています。

(2020/1/3 追記)
正しく知るには公式ドキュメントでページを見ながらの方が詳しく知ることができます。
完成したらあためて読み返すのがいいと思いました。

- [チュートリアル：React の導入 – React](https://ja.reactjs.org/tutorial/tutorial.html)  
- [Hello World – React](https://ja.reactjs.org/docs/hello-world.html)  
- [React 用語集 – React](https://ja.reactjs.org/docs/glossary.html)

また、りあクト！シリーズを読んだら大分理解が深まりました。

Reduxについては、下記の記事を書きましたので、参考にしていただけると嬉しいです。
[[初心者向け]React Redux Basic TutorialにあるTodoAppを今書き直したら - Qiita](https://qiita.com/nori0__/items/6557446792ec1c2ef3d1)  


# 用語集
## React
UI構築のためのJavaScriptライブラリ（フルスタックなフレームワークではない）。
ライブラリとフレームワークの違い: [「ライブラリ」と「フレームワーク」は何が違うのか - Qiita](https://qiita.com/baby-degu/items/7dc4548bf7befc2671f4)
React単体ではスタイリング機能は持っていない。
Facebookが作成。

仮想DOMの仕組みが導入されている。
仮想DOMは、実際のDOMに変換される前のメモリ上にキャッシュされる要素ツリーのことで、Reactでは仮想DOMを比較して差分だけ実際のDOMに反映させている。

公式ページ [React – ユーザインターフェース構築のための JavaScript ライブラリ](https://ja.reactjs.org/)
 では、以下の3つの特徴を掲げている。

- 宣言的な View
 命令型プログラミングの対義語、宣言型プログラミングにもあるように参照透過性が保証されるよう実現されているため、「React はデータの変更を検知し、関連するコンポーネントだけを効率的に更新、描画」が出来る。

- コンポーネントベース
「自分自身の状態を管理するカプセル化されたコンポーネントをまず作成し、これらを組み合わせることで複雑なユーザインターフェイスを構築します。」とあるように部品を組み合わせてUIを構築する。
また、TemplateではなくJavaScriptライブラリであるため、サードパーティーのライブラリの変更など変化に対応しやすい。

- 一度学習すれば、どこでも使える
UIにレンダリングするレンダラーを変えることが出来るため様々なプラットフォームで開発が出来る。
Reactは本体とレンダラーが分離されていること、JSXがXMLを対象としていたことからレンダラーを変えることができるようになっている。

## components
ReactにUIを伝えるための小さく再利用可能な部品。
これを組み合わせてUIを構築する。
チュートリアルで出てくる「React.Componentのサブクラス」がそれにあたる。
データが変更されるとReactが効率的に再レンダリングする。

## JSX
ECMAScript2015(JavaScriptの標準規格)に対するJavaScript の拡張構文でJavaScriptだけで動作する。
つまり、コンパイルするとJavaScriptに変換される。
Facebookが開発した独自タグ技術。
JavaScriptのコードでXMLの要領でUI要素が記述が出来る。
コンポーネントとして認識してもらうには大文字から始める必要がある。
[JSX を深く理解する – React](https://ja.reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized)  


JSXを使う理由として、公式ドキュメントでは、以下のように記載されています。
>表示のためのロジックは、イベントへの応答や経時的な状態の変化、画面表示のためのデータを準備する方法といった、他の UI ロジックと本質的に結合したものであり、React はその事実を受け入れます。
マークアップとロジックを別々のファイルに書いて人為的に技術を分離するのではなく、React はマークアップとロジックを両方含む疎結合の「コンポーネント」という単位を用いて関心を分離します。

[JSX の導入 – React](https://ja.reactjs.org/docs/introducing-jsx.html#gatsby-focus-wrapper)より  

つまり、Viewを疎結合しようとしたらマークアップ(HTML)とロジック(JavaScript)を両方含んだ「コンポーネント」という単位でないと意味がないんだ！ということでしょうか。
Reactでは、疎結合になっているため必要なReact要素のみレンダリングするなどの対応も可能になっており、Reactのレンダリングは速いといわれる所以ですね。


また、JSXはデフォルトでインジェクション攻撃を防いでくれます。
React DomがJSXに埋め込まれた値をレンダー前にエスケープするためXSS攻撃の防止になります。

React専用のものではなく、VueなどでもBabelプリセットの設定を変更すれば使用可能。
react-scriptsパッケージがインストールされている場合Babelによってコンパイルされて、webpackによってバンドルされることでソースコード同士が紐付けされる。

### boolean値
boolean値では何も出力されないため、下記は出力されない、

```jsx
<div>{undefined}</div>
<div>{null}</div>
<div>{true}</div>
```
上記を使って条件によってレンダリングするものを分けるような記述が出来る。

### <> 空タグ
<React.Fragment>の省略記法。
レンダリング対象のJSXでは、トップレベルが1つの要素でないとエラーになるため、<React.Fragment>を使って不要なノードを追加することなく複数の要素をまとめて扱う。
空タグを使うときは空タグの中身のノードが必須のため、処理結果でノードがなくなることはないか注意が必要。

## Reactのインストールパッケージ
react-scriptsのインストールパッケージの一部を紹介。Babelに関しては[こちら](https://qiita.com/nori0__/items/deb9d99a3ba1f270db54#babel)を参照。

### webpack
様々なモジュール構文、ファイル形式のソースコードファイルを1つにまとめるモジュールバンドラ。
1つにまとめておくことで、リクエスト回数を減らすことが出来る。
[webpack](https://webpack.js.org/)  
[Webpackってどんなもの？ - Qiita](https://qiita.com/kamykn/items/45fb4690ace32216ca25)  

### webpack-dev-server
ライブリロード、ファイルの変更を検知して再ビルド・リロードする HTTP サーバー。ホットリロードを実現している。
webpackが使われており開発のみで使用する。
[webpack/webpack-dev-server: Serves a webpack app. Updates the browser on changes. Documentation https://webpack.js.org/configuration/dev-server/.](https://github.com/webpack/webpack-dev-server)  

### dotenv
カレントディレクトリに置かれた.envファイルに定義された値を環境変数としてprocess.envに設定できるモジュール。
.envファイルは、機密情報をコードとは別に環境変数を保存するときに使用するファイル。
process.envはNode.jsの環境変数を格納しているグローバルな変数。
[motdotla/dotenv: Loads environment variables from .env for nodejs projects.](https://github.com/motdotla/dotenv)  


## レンダー
- Reactだけで構築されたアプリは、通常ルートDOMノードをひとつだけ持つ
  - `document.getElementById('root')`を`ReactDOM.render`の引数に持つ物をルートDOMノードと呼ぶ
- Reactの要素はイミュータブル
- ReactDOMは更新が必要なDOMだけ更新する

## ライフサイクルメソッド
クラスコンポーネントにはライフサイクルの各フェーズに対応したメソッドがあり、それをライフサイクルメソッドと呼ぶ。

コンポーネントのライフサイクルの各フェーズとメソッドを図で見る場合は以下が良いです。
[React lifecycle methods diagram](https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/)  

v16.4なら以下のまとめも分かりやすいです。
[React(v16.4) コンポーネントライフサイクルメソッドまとめ - Qiita](https://qiita.com/yuria-n/items/3c3fc8d29fd2e56ed7a9) 

### renderメソッド
UIとして表示したいReact要素を返す。
ReactはReact要素を受け取り、レンダリング結果を表示する。
因みにReact要素以外の型も返せる[^注釈reanderメソッドの型]。

ライフサイクルメソッドの1つでクラスコンポーネントで必須のメソッド。
renderメソッドは、propsやstateが更新されるたびに呼ばれる（そのためここでpropsやstateを操作してはいけない）。

[^注釈reanderメソッドの型]: 詳しくは、[React.Component – React](https://reactjs.org/docs/react-component.html#render) へ  


## props
プロパティの略。親コンポーネントから渡される。

用途: 
親コンポーネントから子コンポーネントへ情報を渡す時に使われる。

特徴:
親コンポーネントから受け取った値は不変であり読み取り専用とする。
親コンポーネントから渡される。

使い方: 

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

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);
```
>1. `<Welcome name="Sara" />` という要素を引数として ReactDOM.render() を呼び出します。
2. React は Welcome コンポーネントを呼び出し、そのときに props として {name: 'Sara'} を渡します。
3. Welcome コンポーネントは出力として `<h1>Hello, Sara</h1>` 要素を返します。
4. React DOM は `<h1>Hello, Sara</h1>` に一致するよう、DOM を効率的に更新します。

[コンポーネントと props – React](https://ja.reactjs.org/docs/components-and-props.html#rendering-a-component)より  

その他特徴:

- 値だけでなくメソッド(例えば、ButtonのonClickメソッドなど)を渡すことも出来る。
- デフォルト値の設定が出来る。
- propsには、呼ばれた側のコンポーネントが暗黙的に渡される。
  - React.createElement() の第3引数に相当する。

## status
コンポーネントが保持する状態。

用途: 
UIに関した状態などを保持する時に使われる。

特徴: 
コンポーネント内で値を変更することが可能。
コンポーネントの内部で制御される。
stateの更新は非同期の場合がある。
stateの更新はマージ(shallow copy)されるため変数ごとに独立して更新できる。

使い方: 

```react
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);
```
>1. `<Clock />` が ReactDOM.render() に渡されると、React は Clock コンポーネントのコンストラクタを呼び出します。Clock は現在時刻を表示する必要があるので、現在時刻を含んだオブジェクトで this.state を初期化します。あとでこの state を更新していきます。
2. 次に React は Clock コンポーネントの render() メソッドを呼び出します。これにより React は画面に何を表示すべきか知ります。そののちに、React は DOM を Clock のレンダー出力と一致するように更新します。
3. Clock の出力が DOM に挿入されると、React は componentDidMount() ライフサイクルメソッドを呼び出します。その中で、Clock コンポーネントは毎秒ごとにコンポーネントの tick() メソッドを呼び出すためにタイマーを設定するようブラウザに要求します。
4. ブラウザは、毎秒ごとに tick() メソッドを呼び出します。その中で Clock コンポーネントは、現在時刻を含んだオブジェクトを引数として setState() を呼び出すことで、UI の更新をスケジュールします。setState() が呼び出されたおかげで、React は state が変わったということが分かるので、render() メソッドを再度呼び出して、画面上に何を表示すべきかを知ります。今回は、render() メソッド内の this.state.date が異なっているので、レンダリングされる出力には新しく更新された時間が含まれています。それに従って React は DOM を更新します。
5. この後に Clock コンポーネントが DOM から削除されることがあれば、React は componentWillUnmount() ライフサイクルメソッドを呼び出し、これによりタイマーが停止します。

[state とライフサイクル – React](https://ja.reactjs.org/docs/state-and-lifecycle.html)より  

その他特徴:

- 定義したReact componentに対して閉じている（privateであるべき）。
- 初期化はReact componentのコンストラクタで行う。
- 状態を保持する場所は、状態を変更するReact componentより上位のコンポーネントで行う(stateのリフトアップ)。
- immutableにすべき
  - statusで保持しているオブジェクトを更新するときは、オブジェクト自体の参照を変更する（配列だったら配列のコピーを参照するようにする）ようにする。
  - そもそもconstなど不変なオブジェクトにする。

immutableにする理由としては

  - 複雑な機能が簡単に実装できる
    - 状態を戻しやすい
  - 変更の検出がしやすい
    - 可変だと、前の状態を知るのが困難、変更されたか確認するのにオブジェクトツリーごと比較する必要が出てきたりする。
  - React の再レンダータイミングの決定
    - 再レンダリングが必要かどうか（変更されたかどうか）が分かりやすい。
    - React で pure component を構築しやすい。

### setStateメソッド
コンポーネント内で呼び出すことで、stateの値を更新する。
stateオブジェクトが新しいstateオブジェクトに置き換えられ、コンポーネントのrenderメソッドが実行されて再レンダリングする。
setStateメソッドは非同期で呼び出される。

## propsとstatusの変更

|                                                   | props | state | 
| ------------------------------------------------- | ----- | ----- | 
| 親コンポーネントから初期値を取得できますか？      | Yes   | Yes   | 
| 親コンポーネントによる変更ができますか？          | Yes   | No    | 
| コンポーネント内でデフォルト値を設定できますか？* | Yes   | Yes   | 
| コンポーネント内で変更できますか？                | No    | Yes   | 
| 子コンポーネントの初期値を設定できますか？        | Yes   | Yes   | 
| 子コンポーネント内で変更できますか？              | Yes   | No    | 

*親から受け取ったpropsとstateの初期値の両方が、コンポーネント内で定義されたデフォルト値を上書きすることに注意してください。
[react-guide/props-vs-state.md at master · uberVU/react-guide](https://github.com/uberVU/react-guide/blob/master/props-vs-state.md)より (英訳)  


# 参考文献
[コンポーネントの state – React](https://ja.reactjs.org/docs/faq-state.html)  
[Lucy | ReactJS: Props vs. State](https://lucybain.com/blog/2016/react-state-vs-pros/)  
[React における State と Props の違い - Qiita](https://qiita.com/kyrieleison/items/78b3295ff3f37969ab50)  
[りあクト！ TypeScriptで始めるつらくないReact開発 第3版【Ⅱ. React基礎編】 - くるみ割り書房 ft. React - BOOTH](https://oukayuka.booth.pm/items/2368019)