#はじめに
hooksと普段から呼んでいるが、javascript関数と厳密に言えばどういうところが違うのだろうと思い調べた。
#前提
hooks、javascriptともにアロー関数を想定。ここで言うjavascript関数はtypescript関数を含む(どちらかというとtypescriptより)。
#hooksとは
hook,hooks,フック,Hooks API,React Hooksなどいろいろな呼び方がありますがすべて一緒です。
フック (hook) は React 16.8 で追加された新機能です。state などの React の機能を、クラスを書かずに使えるようになります。
React公式[[1]]より引用。
要するにクラスコンポーネントじゃなくて関数コンポーネントでもstateなどのReactの機能を使うためのもの。useState、useEffectなどは特によく使う。自分独自にフックを作成することも出来、自分が作成したフックをカスタムフックと呼びます。
自分独自のフックを作成することで、コンポーネントからロジックを抽出して再利用可能な関数を作ることが可能です。
React公式[[2]]より引用。
公式ではカスタムフックを作成することでロジック(論理的構造)を切り出すことが可能であるとアナウンスされています。しかしこの表現が僕がhooksを誤解した原因の文です(あとで詳細を述べます)
#hooksのルール
React公式[[3]]を参考に作成。
フックを呼び出すのはトップレベルのみ
hooksはif文などの条件分岐の中や、for文などのループの中、ネストされた関数内では使用してはいけません。当然イベントハンドラとしても利用不可能です。
フックを呼び出すのはReactの関数内のみ
hooksはjavascript関数からは呼び出してはいけません。呼び出せる場所は以下の2つです。
・Reactの関数コンポーネント内
・カスタムフック内
「Reactの関数コンポーネント」という定義がよく分からなかったので実験してみた感じ、JSXを返り値とする大文字から始まるjavascript関数のことのようです。
**この2つのルールは絶対守らなければならないものです。**あとは命名規則として「useXXXX」という名前にするというのもあります。こうするとESLintプラグインなどで認識してくれるので基本的にはこの命名規則に従うべきでしょう。
#カスタムフックと自作javascript関数は何が違うのか。
さていよいよ本題です。2つの違いを列挙していきましょう。
|項目|カスタムフック|自作js関数|
|::|::|::|
|トップレベル以外での使用|不可能|可能|
|hooksの使用|可能|不可能|
|命名規則|基本「useXXXX」|基本自由|
|返り値|なんでも可能|JSXは不可能|
カスタムフックはトップレベル以外で使えない。自作js関数は使える
これが一番大きな違いでしょう。トップレベル以外では必然的に自作js関数を使うことになります。
カスタムフック内ではフックが使用可能、自作js関数では不可能
ロジック内でフックを使用したい場合はカスタムフックを使用しなければなりません。
カスタムフックの命名は基本「useXXXX」、自作js関数の命名は基本自由
カスタムフックは基本的に「useXXXX」にしないと怒られることが多いですし、そうしたほうが明らかにわかりやすいです。自作js関数のほうは特に決まっていなければ自由です。
カスタムフックはJSXを返り値に出来る、自作js関数は出来ない
これはそもそもアンチパターンなのであまり気にする必要はないと思うのですが、自分の環境では上のような結果になりました。これも「useXXXX」の命名規則による認識が効いている気がします。当然もしJSXを返したかったら拡張子もjsx(tsx)にしなければいけませんし、基本返さない方がいいと思います。
#具体的な使い分け
イベントハンドラのロジックを切り出したい
トップレベルではないので自作js関数。stateを変更したい場合はstateの更新関数(setState()など)をコールバック関数として引数に渡せば自作js関数に出来ます。reduxのdispatchなどを使う場合も多いとは思います。
DBからのデータの取得ロジックにuseEffectを使いたい
hooksを使いたいのでカスタムフックです。api処理は別に切り出す必要があるかもしれませんがそれはまた別の話です。
#おわりに
「hooksはロジックを切り出すのにトップレベルじゃないと使えない、じゃあイベントハンドラとかのロジックを切り出す場合はどうすればいいんだ!」と思っていろいろ調べていたんですが、単純にjs関数使えばいいだけでした。書き方的にhooksですべてロジック切り出せるのかと思ってたので、気づくのに時間がかかってしまいました。まだ非同期処理周りが曖昧なので、また何かまとめたら投稿しようと思います。
#参考文献
[1]:https://ja.reactjs.org/docs/hooks-intro.html
[2]:https://ja.reactjs.org/docs/hooks-custom.html
[3]:https://ja.reactjs.org/docs/hooks-rules.html
[[1]]:フックの導入
[[2]]:独自フックの作成
[[3]]:フックのルール