React入門 学習メモ

# はじめに
以下の知識の習得を目的として行った学習メモになります。

- Reactの基礎知識
- JSXについて
- create-react-appでの環境構築
- Reactコンポーネントの作り方
- モジュールのimport、exportについて
- React Hooksについて

# Reactの基礎知識
## Reactとは？
- Facebookが開発
- JavaScriptのライブラリ（フレームワークではない）
- WebのUIを作る
- React ≠ SPA

## コンポーネントとは？
UIは2つに分類される
1. 見た目（View）
2. 機能（Controller）

コンポーネント = 見た目 + 機能

Webページはコンポーネントのツリー構造になっている

###なぜコンポーネントを使うのか
- 再利用性するため
- 分割統治するため
- 変更に強くするため

## Virtual DOM
###そもそもDOMとは？
→ Document Object Modelの略
→ インターフェース
→ HTMLにアクセスする窓口
→ HTML構造、見た目、コンテンツを変更したいときはDOMを通して操作を行う

###Virtual DOMとは？
Reactで管理するDOM。
通常のDOMはブラウザのレンダリングによって管理されるが
Reactではブラウザのレンダリングと別で管理を行う
→効率よくDOM操作できる

通常のDOM操作

```javascript
document.getElementById('hoge').innerText='fuga';
```

ReactのVirtual DOM操作

```javascript
render(
  <div id='hoge'>fuga</div>
);
```

##差分描画
Reactでは変更されたVirtual DOMの**差分**のみを再描画する

##JSX
JavaScript内でHTMLっぽく書ける

```javascript
ReactDOM.render(
  <div className={hoge}>
    <h1>Hello World!</h1>
  </div>
)
```

#JSXの基礎知識と文法

##JSXとは？
- JavaScript内でHTMLを簡単に記述するための言語
- JavaScriptの拡張言語
- Facebookが開発
- React公式ドキュメントはほぼJSXで記述されている
- Reactでは業界標準

##なぜJSXを使う？
通常のJavaScriptでHTMLを記述（DOM操作）

```javascript
const fuga = "<h1>Hello, World!</h1>"
document.getElementById('hoge').innerHTML = fuga;
```

量が増えると。。

```javascript
const fuga = "<h1>Hello, World!</h1>"
const foo = "<h2>React Commentary</h2>"
const bar = "Hi, I'm Billy Gibbons."
document.getElementById('hoge').innerHTML = fuga;
document.getElementById('foo').innerHTML = foo;
document.getElementById('bar').innerHTML = bar;
```

JSXを使うと。。

```javascript
return (
  <React.fragment>
    <div id="hoge">
      <h1>Hello, World!</h1>
    </div>
    <div id="foo">
      <h2>React Commentary</h2>
    </div>
    <p id="foo">Hi, I'm Billy Gibbons.</p>
  </React.fragment>
)
```

可読性が高い！

ただJSXは実際のところJavaScriptではない。
JSXの構文をブラウザは理解できない。

そこでトランスパイラが必要。

##トランスパイラ
「翻訳」のような役割。
JSX → JavaScript(ES6) → JavaScript(ES5)

Reactのトランスパイラは**Babel**

トランスパイラを主たる実装として開発されている言語の例
CoffeeScript、TypeScript...etc

##もしJSXがなかったら。。
React.createElementを使う

```javascript
React.createElement(
  "h1",
  null,
  "Hello, World!"
)
```

JSXを使用して記述したJSをBabelでトランスパイルするとReact.createElementを使用した形に変換される

##JSXの基本文法
1.Reactパッケージのインストールが必要

```javascript
// .jsxファイル内の先頭に宣言
import React from "react";
```

2.HTMLとほぼ同じ文法（ただ`class`は`className`に）

```javascript
const App = () => {
  return (
    <div id="hoge" className="fuga">
      <h1>Hello, World!</h1>
    </div>
  );
};
```

3.`{}`内に変数や関数を埋め込める

```javascript
const foo = "<h1>Hello, World!</h1>"
const App = () => {
  return (
    <div id="hoge" className="fuga">
      {foo}
    </div>
  );
};
```

4.変数名などは全てキャメルケースで記述する

```javascript
const fooBar = "<h1>Hello, World!</h1>"
const App = () => {
  return (
    <div id="hoge" className="fuga">
      {fooBar}
    </div>
  );
};
```

5.空要素は閉じる

```javascript
const App = () => {
  return (
    <div id="hoge" className="fuga">
      <input type="text" id="blankElement" />
      <img src="/assets/icon/icon.png" />
    </div>
  );
};
```

# 環境構築
##create-react-app

###必要なもの
- node 8.10以上
- npm 5.6以上

上記インストールのためにhomebrew、nodebrewが必要

####homebrewのインストール
https://brew.sh/index_ja

####nodebrewのインストール

```
$ brew install nodebrew
$ nodebrew -v // インストールの確認
```

####nodeのインストール

参考：https://qiita.com/kyosuke5_20/items/c5f68fc9d89b84c0df09

```
$ nodebrew ls-remote // インストール可能なnodeのバージョン確認
$ nodebrew install stable // 安定版のインストール
$ nodebrew ls // 現在インストールされているnodeのバージョン一覧
$ nodebrew use v{インストールしたバージョン} // currentへの追加
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zprofile // zshの場合
```

####npmのインストール

nodeを入れた時点でnpmも入る
バージョンが5.6以上であることを確認する

```
npm -v
```

###create-react-appによるプロジェクトの作成

```
$ npx create-react-app react-blog-app
```

###create-react-appとは
React開発環境を超簡単に構築できるツール。
**Reactを学習するのに最適な環境**
(React公式documentから引用)

- React開発環境の構築は難しい
- トランスパイラのbabelやバンドラーのwebpackの設定が必要

create-react-appなら1コマンドで環境を整えてくれる

###create-react-appの環境構成
1. `src` : コンポーネントを作るJSファイルなど
2. `public` : htmlファイルや設定ファイルなど。`manifest.json`はPWAを開発する際に使用する設定ファイル
3. `build` : 本番環境用のファイル

###基本コマンド

```
$ npm run build
```
srcとpublic内のファイルを1つにまとめて（バンドル）、buildディレクトリに出力する

```
$ npm start
```
ローカルサーバを起動してReactアプリを動かす

```
$ npm run eject
```
babelやwebpackの設定を変更したい時に使用する

##その他の環境構築ツール
- Next.js → サーバーサイドレンダリング（SSR）
- Gatsby → 静的ウェブサイトに最適（SSG）

#コンポーネントの基本

## コンポーネントとは？
UIは2つに分類される
1. 見た目（View）
2. 機能（Controller）

コンポーネント = 見た目 + 機能

Webページはコンポーネントのツリー構造になっている

##なぜコンポーネントを使うのか
- 再利用性するため
- 分割統治するため
- 変更に強くするため

##コンポーネントの種類
1. `Class Component` : クラスによって定義されたコンポーネント
2. `Functional Component` : 関数型で定義されたコンポーネント

###Functional Component
- ES6のアロー関数で記述
- stateを持たない（stateless）
- propsを引数に受け取る
- JSXをreturnする
- **シンプル**

```Article.jsx
import React from 'react';

const Article = (props) => {
    return (
        <div>
            <h2>{props.title}</h2>
        </div>
    );
};

export default Article;
```

###Class Component
- React.Componentを継承
- ライフサイクルやstateを持つ
- propsにはthisが必要
- renderメソッド内でJSXをreturnする

```Article.jsx
import React from 'react';

class Article extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <div>
              <h2>{this.props.title}</h2>
            </div>
        );
    }
}

export default Article;
```

###最近の主流はFunctional Component
- 記述量が少ない
- コンポーネントにstateを持たせたくない

##propsでデータを受け渡す

親コンポーネント

```Blog.jsx
import React from 'react';
import Article from "./Article";

const Blog = () => {
    return (
        <React.Fragment>
            <Article title={'Hello, React'}/>
        </React.Fragment>
    );
}

export default Blog;
```

子コンポーネント

```Article.jsx
import React from 'react';

const Article = (props) => {
    return (
        <div>
            <h2>{props.title}</h2>
        </div>
    );
};

export default Article;
```

###受け渡せるデータ型
- `{}`内に記述
- 文字列、数値、真偽値、配列、オブジェクトなどなんでも渡せる
- 文字列は`{}`なくてもOK


```Blog.jsx
import React from 'react';
import Article from "./Article";

const Blog = () => {
    const authorName = 'Eric Clapton';
    return (
        <React.Fragment>
            <Article
                title={'Hello, React.'}
                order={3}
                isPublished={true}
                author={authorName}
            />
        </React.Fragment>
    );
}

export default Blog;
```

###再利用する
コンポーネントは再利用できることが最大の利点

```Blog.jsx
import React from 'react';
import Article from "./Article";

const Blog = () => {
    const authorName = 'Eric Clapton';
    return (
        <React.Fragment>
            <Article title={'出生について'}/>
            <Article title={'Cream時代'}/>
            <Article title={'ソロ活動時代'}/>
        </React.Fragment>
    );
}

export default Blog;
```

#コンポーネントの状態
stateの設定と取得と変更

##状態（state）とは
- コンポーネントの中で管理する変数
- ローカルステートと呼ばれる
- propsとして子コンポーネントに渡せる

##なぜstateを使うのか
- render()内では値を変更してはいけない
- setState()で値を変更する
- stateの変更 = 再レンダーのきっかけ<br/>→ページをリロードせずに表示を切り替えられる

##stateの設定方法
- Class Componentが前提
- constructor()内で宣言
- オブジェクト型で記述

```Blog.jsx
import React from 'react';
import Article from "./Article";

class Blog extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            isPublished: false
        }
    }
    // 略
}

export default Blog;
```

##stateの取得
- 同コンポーネント内なら`this.state.key名`で取得できる
- 子コンポーネントで参照したい場合はpropsとして渡す

```Blog.jsx
render() {
  return (
    <React.Fragment>
      <Article
        title={'出生について'}
        isPublished={this.state.isPublished}
      />
    </React.Fragment>
  );
}
```

##stateの変更方法
- setState()を使う
- 関数にラップするのが一般的
- setState()内に記述されたstateのみを変更

```Blog.jsx
    // 公開状態を反転させる関数を定義する
    togglePublished = () => {
        this.setState({
           isPublished: !this.state.isPublished
        });
    }
```

#コンポーネントのライフサイクル
##ライフサイクルとは
- コンポーネントの「時間の流れ」
- 生成、変更、破棄までの循環
- それぞれの段階で必要な処理を記述

##３種類のライフサイクル
`Mounting`：コンポーネントが生成される期間
`Updating`：コンポーネントが変更される期間
`Unmounting`：コンポーネントが破棄される期間

##なぜライフサイクルを使うのか
- `関数外に影響を与える関数`を記述するため<br/>e.g. DOM変更、API通信、ログ出力、setState() ...etc
- 副作用 = 適切な場所に配置すべき処理

|order|Mounting|Updating|Unmounting|
|:--|:-:|:-:|:-:|
|1|constructor()|||
|2|render()|render()||
|3|componentDidMount()|||
|4||componentDidUpdate()||
|5|||componentWillUnmount()|

##主要メソッド
###Mount
`constructor()`：初期化（stateなど）
`render()`：VDOMを描画（JSXをreturn）
`componentDidMount()`：render()後に一度だけ呼ばれる。リスナーの設定やAPI通信に使われる。

###Updating
`render()`：VDOMを描画（JSXをreturn）
`componentDidUpdate()`：再render()後に呼ばれる。スクロールイベントや条件付きイベント。

###Unmounting
`componentWillUnmount()`：コンポーネントが破棄される直前に呼ばれる。リソースを解放するために使う。（リスナーの解除など）

#importとexport

##モジュール化について
- 他言語では昔からある概念
- JavaScriptではES2015(ES6)から採用
- 基本的に1ファイル=1モジュール
- 任意の場所で読み込んで使用できる

##モジュール化のメリット
1. 分割統治できる<br/>大規模プログラムでも管理しやすくなる
2. 任意の場所で読み込める<br/>必要なものを必要な分だけ
3. 再利用できる<br/>何度も同じコードを書かなくていい

##名前付きexport
1モジュールから複数の関数をexport
クラスはexportできない

```index.js
export function Foo() {
  return (
    <h1>FOO</h1>
  );
}
export const Bar = () => {
  return (
    <h1>BAR</h1>
  );
}
```

##名前なし(default)export
- 1ファイル(1モジュール) 1export
- **ES6で推奨されているexport方法**
- アロー関数は宣言後にexport
- クラスをexportできる

```Foo.js
export default function Foo() {
  return (
    <h1>FOO</h1>
  );
}
```

```Bar.js
const Bar = () => {
  return (
    <h1>BAR</h1>
  );
}
export default Bar;
```

```Hoge.js
export default class Hoge extends Fuga {
  render() {
    return (
      <h1>Hoge</h1>
    );
  }
}
```

##モジュール全体のimport
- 名前なし(default)exportしたモジュールをimportする
- モジュール全体のimport

```Blog.jsx
import React from 'react';
import Article from "./Article";
```

```Article.jsx
const Article = (props) => {
  return (
    <div>Article</div>
  );
}
export default Article;
```

##関数ごとのimport
- 名前付きexportされたモジュールをimportする
- {}内にimportしたい関数名

```Hoge.js
import { Foo, Bar } from "./FooBar";
```

```FooBar.js
export function Foo() {
  return (
    <h1>FOO</h1>
  );
}
export const Bar = () => {
  return (
    <h1>BAR</h1>
  );
}
```

##別名import
- 別名（エイリアス）をつけてimportできる
- モジュール全体なら `* as name`
- モジュール一部なら `A as B`

```Blog.jsx
import React from 'react';
import * as AnotherName from './Article';
import { Foo as MyFoo } from './FooBar';
```

```Article.js
const Article = (props) => {
  return (
    <div>Article</div>
  );
}
export default Article;
```

#React Hooks
関数コンポーネントでもstateを扱う

##Hookとは
- クラスの機能(stateやライフサイクル)を`Functional Component`でも使える機能
- React 16.8から導入された(2020/2に正式リリース)
- 100%後方互換<br/>→古い書き方をしているコンポーネントなどに影響を及ぼさない<br/>→小さく導入できる

##なぜHookを使うのか
###シンプルさを保つため
- `Class Component`は複雑になりやすい
  - `this`という悪魔
  - stateを扱うロジックが複雑
  - **複数のライフサイクルメソッド**に副作用のある処理がまたがる

##`useState()`を使う
- ステートフックと呼ばれる
- クラスコンポーネントでいう`this.state`と`this.setState()`の代替
- 複数のstateを扱うときはstate毎に宣言する

1.useState関数をインポート

```javascript
import React, {useState} from 'react';
```

2.宣言する

```javascript
const [isPublished, togglePublished] = useState(false);
```

3.JSX内で使う

```javascript
<input /略/ onClick={() => togglePublished(!isPublished)} />
```

##Functional Componentでもライフサイクルを扱う

`useEffect()`を利用する

###`useEffect()`のメリット
- ライフサイクルメソッドを代替できる
- Functional Componentでライフサイクルを扱える
- コードをまとめることができる
  - 🙆‍♀️ 機能ベース（何をやっているのか）
  - 🙅‍♀️ 時の流れベース（ライフサイクルのメソッド毎）

##`useEffect()`の仕組み
- レンダー毎に`useEffect()`内の処理が走る
- 代替できるメソッド
  - `componentDidMount()`
  - `componentDidUpdate()`
  - `componentWillUnmount()`

##`useEffect()`の使用

###パターン① レンダー毎

```javascript
useEffect(() => {
  console.log('Render!');
  return () => {
    console.log('Unmounting!');
  }
})
```

- 基本形
- `useEffect()`内にCallback関数を書く
- Callbackはレンダー毎に呼ばれる
- returnするCallback関数はアンマウント時に呼ばれる。（クリーンアップ関数）

###パターン② マウント時のみ実行

```javascript
useEffect(() => {
  console.log('Render!');
}, [])
```

- 第二引数の配列内の値を前回レンダーと今回レンダーで比較
  - 変更があればCallback関数を実行
- 第二引数に空の配列を渡すと最初の１回（マウント時）のみ実行される

###パターン③ マウント&アンマウント時に実行

```javascript
useEffect(() => {
  console.log('Render!');
  return () => {
    console.log('Unmounting!');
  }
}, [])
```

- ①と②の複合形
- 通常のCallbackはマウント時のみ
  - 配列が空の場合はUpdating期間は処理が実行されない
- アンマウント時はretrun内のクリーンアップ関数が実行される

###パターン④ 特定のレンダー時に実行

```javascript
const [limit, release] = useState(true);

useEffect(() => {
  console.log('Render!');
}, [limit])
```

- マウント時に実行される
- limitの値が変わった時に実行される