2020/08/03

ReactHookのおさらい

WRITER: y.harada

フックとはReactのstateやライフサイクルを関数コンポーネントで利用するための機能です。
クラスコンポーネントでは使うことが出来ません。

代表的なフック

ステートフック

状態を管理するためのフックです
クラスコンポーネントでのsetStateに当たります。
useStateを呼び出すことで、状態を管理する変数と関数が返ります。
下記の例ではcountが状態の入った変数で、setCountが状態を更新するための変数です。
useStateの引数で状態の初期値を設定することが出来ます。

この状態でcount変数を描画させると初期値の0が表示されます。

状態を更新するにはsetState関数を使います
今回はuseStateで受け取ったsetCountがそれに該当します。
下の例ではクリック時にsetCountを呼び出してcountを+1するボタンを追加しました

またsetStateに関数を渡すことで前回の状態を利用することが出来ます

副作用フック

副作用フックとはcomponentDidMount、componentDidUpdateなど
クラスコンポーネントのライフサイクルを利用するためのフックです。
useEffectに関数を渡す形で利用します。

上記の例を先程のカウントコンポーネントに追加してみます

ブラウザをリロードするとコンソールにログが表示され、
CountUpボタンを押して状態を更新してみると、countの更新とともにコンソールのログが増えていくことが確認できます。


このようにcomponentDidMount、componentDidUpdateのタイミングでuseEffectが実行されていることがわかります

コンポーネントが更新されるたびにuseEffectが実行されることがわかりましたが、
useEffectの第二引数に配列を渡すことで実行を制御することが出来ます。
これを依存配列と呼びます。
まずは先程のuseEffectの第二引数に空の配列を渡してみます。

ブラウザをリロードするとコンソールにログが表示されますが、
count変数を更新してもログは表示されません。


このように空の配列を追加したことで依存する状態がないと判断され、

コンポーネントの更新ではuseEffectは実行されません。

次に、count変数をAとBに分け、useEffectの依存配列にcountAを追加します

この場合、countAが更新されるとuseEffectが実行されますが、countBを更新してもuseEffectは実行されません。


このように、依存する状態変数を指定することでuseEffectの実行を制御することが出来ます。

コンテキストフック

コンテキストとはpropsを介さずにコンポーネント間でデータを渡す機能です。
コンポーネントフックとステートフックを利用することで、グローバルな状態管理を行うことが可能になります。

適当な子コンポーネントをカウンターコンポーネントに追加します。

親コンポーネントでコンテキストを作成しexportしておきます。
これは子コンポーネントでimportするためです。

次にコンテキストのプロバイダコンポーネントで、子コンポーネントを囲みます。

親コンポーネントの最終的な形がこちらです。

valueはコンテキストによって渡すデータです。

子コンポーネントでコンテキストのvalueを受け取るには
CountContextをimportしてuseContextの引数に渡すことでvalueを受け取ることが出来ます

子コンポーネントの最終的な形になります。

コンテキストによって渡されたデータが表示されていることが確認できます。

コンテキストでステートフックを渡すとどうなるでしょうか
親コンポーネントでステートフックを定義し、valueに渡します。
今回count変数の表示は親で行います。

子コンポーネントでcountのステートフックを受け取り、
クリック時に+1するボタンを追加します。

このカウントアップ処理が親のcount変数に反映されていることが確認できます。

カスタムフック

フックを利用するにはコンポーネントである必要はなく、
別の関数にフックを抽出することでコンポーネントとロジックを分離し、
再利用可能な独自のフックを作成することができます。

今回のカウントコンポーネントからuseStateフックを抽出してみます。
カスタムフックの作成はコンポーネントに作成したフックをそのままコピーするだけで、
何も特別なことは必要ありません。
今回はcountをカウントアップ、カウントダウンする関数も追加しました。
最後にコンポーネントで使用する変数や関数をreturnしておきます。

カウントコンポーネントではimportしたuseCountを実行して
count変数とcountUp, countDown関数を受け取ります。
あとはuseStateの時と同じように使うだけです。

カスタムフック内のuseStateが機能していることがわかります

フックに対応したライブラリ

主要なReactライブラリにはフックを提供しているものがあります。

ReactRouter

例えばReactRouterにはhistoryを返すuseHistory、
URLのクエリからパラメータを取得して返すuseParamsなど

Redux

Reduxではdispatch関数を返すuseDispatch、storeからstateを取得するためのuseSelectorなど
Reduxのフックを利用することでconnectなどの煩雑な処理をする必要がなくなり(多少は)簡潔な利用が可能になります

またReduxフックをカスタムフックとしてコンポーネントから抽出することで、
グローバルで再利用可能な状態管理を実現することができます。

y.harada

y.harada

Unityエンジニア
Reactが好き