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


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

ざっくりQ&A

Q. Reactが大きく変わるって本当?

A. Yes、クラスコンポーネントから関数コンポーネントがメインになる。

Q. クラスじゃないならライフサイクルメソッドはどうすればいいの?

A. 代わりにHooksという関数群が用意されている。

Q. 今すぐ移行しないとダメなの?

A. No、しばらくは新しい機能が追加されるだけなので、これまで通り使える。

Q. Hooks使うと何かいいことあるの?

A. 再利用性の高いコンポーネントが作れる。同じ機能でもスッキリ記述できる。

関数コンポーネントがメインになる

関数コンポーネント+状態管理関数群の形を取ることで、状態管理を含むコンポーネントでも再利用性の高いものを作れるようにするのが狙いのようです。
Introducing Hooksによると、

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

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

新機能・Hooksが追加される

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

ざっくりHooks

詳細は公式に任せて、ここでは概要だけまとめます。

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

Hooksを使うルール

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

カスタムHooks

実際には上記のHooksを組み合わせてカスタムHookを作り、再利用していく形になりそうです。

他にもあるよ、関数コンポーネント推し機能

v16.6.0から追加された2つの機能も紹介します。

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

まとめ

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

余談

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

参照