React、Hooks、それからそれから。

こんにちは。[テプコン](http://www.tepco.co.jp/ep/tepcon/)の声はフット岩尾だそうですよ、でおなじみputanです。
Hooks周り（v16.8.2現在）について、自分の開発チーム向けにまとめたいと思います。

## ざっくりQ&A
### Q. Reactが大きく変わるって本当？
A. Yes、クラスコンポーネントから関数コンポーネントがメインになる。

### Q. クラスじゃないならライフサイクルメソッドはどうすればいいの？
A. 代わりにHooksという関数群が用意されている。

### Q. 今すぐ移行しないとダメなの？
A. No、しばらくは新しい機能が追加されるだけなので、これまで通り使える。

### Q. Hooks使うと何かいいことあるの？
A. 再利用性の高いコンポーネントが作れる。同じ機能でもスッキリ記述できる。

## 関数コンポーネントがメインになる
関数コンポーネント＋状態管理関数群の形を取ることで、状態管理を含むコンポーネントでも再利用性の高いものを作れるようにするのが狙いのようです。
[Introducing Hooks](https://reactjs.org/docs/hooks-intro.html)によると、

- 再利用性の高めようとすると
  - `render props`とか`HOC`みたいな工夫を使うことになりwrapper地獄になりがち
- 高機能コンポーネントを作ろうとすると
  - ライフサイクルメソッドが膨らんでバグの温床になりがち
  - local stateの影響でコンポーネントの分割が難しくなりがち
  - 結果的にRedux等に頼るしかなくてコンポーネント単体の再利用価値が下りがち
- そもそもクラスで書くと
  - JSでのクラス機能をしっかり理解しないといけないがち
  - クラス形、関数形と2つあると使い分けで悩むがち
  - AoT Compile（事前コンパイル）は将来有望だが、クラスはそれを阻害するがち

という問題が顕在化してきたため、これらを解決するために変えていくとのことです。

## 新機能・Hooksが追加される
ライフサイクルを含む状態管理関数群としてHooksが v16.8.0 から正式版として採用されています。
入り口としては**「クラスコンポーネントでできていたことを関数コンポーネントでもできるようにするもの」**と捉えて、細かな違いは触りながら理解していくのが良さそうです。

### ざっくりHooks
[詳細は公式](https://reactjs.org/docs/hooks-reference.html)に任せて、ここでは概要だけまとめます。

| 関数名 | 概要 | 比較対象 |
|:--|:--|:--|
| useState | ローカルの状態とそのセッターを作る | setState |
| useEffect | データfetchやDOM操作などコンポーネントへの副作用を扱う | componentDidMount<br>componentDidUpdate<br>componentWillUnmount |
| useContext | バケツリレーなしに子孫に値を渡す | createContext<br>Provider<br>Consumer |
| useReducer | redux風の状態管理ができる | Redux |
| useMemo | 値をキャッシュして無駄防止 | shouldComponentUpdate |
| useCallback | 関数をキャッシュして無駄防止 | shouldComponentUpdate |
| useRef | クラスのインスタンス変数的な物を作る | インスタンス変数 |
| useImperativeHandle | コンポーネントのメソッド的な物を作る（useRefと組み合わせて呼び出す） | インスタンスメソッド |
| useLayoutEffect | 視覚的な更新に絡んでくる版useEffect | useEffect |
| useDebugValue | デバッグ用 | - |

### Hooksを使うルール
1. 常に同じ数のHooksが同じ順番で呼ばれるようにする。ループや分岐に入れてはダメ。
2. 関数コンポーネントでしか使えない。

### カスタムHooks
実際には上記のHooksを組み合わせて[カスタムHook](https://reactjs.org/docs/hooks-custom.html)を作り、再利用していく形になりそうです。

## 他にもあるよ、関数コンポーネント推し機能
v16.6.0から追加された2つの機能も紹介します。

| 関数名 | 概要 | 比較対象 |
|:--|:--|:--|
| React.memo | 関数コンポーネントにshouldComponentUpdateを使える | shouldComponentUpdate<br>PureComponent |
| React.Suspense | ローディング表示をフラグstate(props)なしで実現できる | |

## まとめ
- Reactは関数コンポーネントメインに消極的に移行していく
- 小さいコンポーネントからHooksを使い始めて慣れておくと良い
- 英語だけど公式ドキュメントに全部載っているので読んでみよう

## 余談
今までは関数コンポーネントの正式名称は`Stateless Functional Component`でしたが、Hooksによってstatelessではなくなるので、`Function Component`という名称になったようです。

## 参照
- [Introducing Hooks](https://reactjs.org/docs/hooks-intro.html)
  - [React Hooks導入の動機](https://qiita.com/tatane616/items/9d667e32b6f82f9f7a9f)
  - [Angular AoTガイド](https://qiita.com/Quramy/items/a603ddb47d6e4b3497e1)
  - [React Hooks をどう使っていくか](https://mizchi.hatenablog.com/entry/2018/11/09/125252)
- [Hooks API Reference](https://reactjs.org/docs/hooks-reference.html#uselayouteffect)
  - [useContextのしくみ](https://qiita.com/ossan-engineer/items/8f2640e4ee053b353943)
  - [React Hook ( useLayoutEffect )](https://codesandbox.io/s/81on3068w9?from-embed)
- [Building Your Own Hooks](https://reactjs.org/docs/hooks-custom.html)
  - [作って理解するReact Hooks](https://qiita.com/uhyo/items/27a83d9044945034c4da)
- [React v16.6.0: lazy, memo and contextType](https://reactjs.org/blog/2018/10/23/react-v-16-6.html)
  - [React 16.6で追加されたReact.Suspenseについて](https://qiita.com/yoshi_ksk/items/706acf084a7f2c560b26)