はじめに
今回はReactでの開発を始めたての筆者が、頻出するhookについて、備忘録がてらまとめてみたいと思います。
useState
useState()は、関数コンポーネントでstateを管理(stateの保持と更新)するためのReactフックであり、最も利用するであろうフックです。
stateとはコンポーネントが内部で保持する「状態」のことで、画面上に表示されるデータ等、アプリケーションが保持している状態を指しています。stateはpropsと違い後から変更することができます。
1 2 | //const [状態変数, 状態を変更するための関数] = useState(状態の初期値); const [count, setCount] = useState(initialState) |
1つ目の要素:stateの現在の値
2つ目の要素:stateの現在の値を更新するための関数
state が更新されてもinitialStateはinitialStateとして保持される
useStateの左辺のstate変数には任意の名前を付けることが出来ます。
基本的には扱いたいstate名にsetをつけたものになると思います。
再レンダリング後もReactはその変数の現在のstateの値をそのまま持っており 、最新のstateの値を関数に渡します。現在のstateの値を更新したい場合は、setStateを呼びます。
useEffect
useEffectを使うと、useEffectに渡された関数はレンダリングの結果が画面に反映された後に動作します。
つまりuseEffectとは、「関数の実行タイミングをReactのレンダリング後まで遅らせるhook」です。
副作用の処理(DOMの書き換え、変数代入、API通信などUI構築以外の処理)を関数コンポーネントで扱えます。
クラスコンポーネントでのライフサイクルメソッドに当たります。
useEffect()の基本構文は以下の通りです。関数コンポーネントのトップレベルで宣言します。
1 2 3 4 | useEffect(() => { /* 第1引数には実行させたい副作用関数を記述*/ console.log('副作用関数が実行されました!') },[依存する変数の配列]) // 第2引数には副作用関数の実行タイミングを制御する依存データを記述 |
第2引数を指定することにより、第1引数に渡された副作用関数の実行タイミングを制御することができます。Reactは第2引数の依存配列の中身の値を比較して、副作用関数をスキップするかどうかを判断します。
また、第2引数を省略することもできますが、コンポーネントがレンダリングされるたびに副作用関数が実行されてしまい、無限ループの温床になりやすいので注意する必要があります。実際には、第2引数を省略するケースはほとんどありません。
では、副作用関数を初回レンダリング時の一度だけ実行させたい場合はどうするかというと、第2引数に空の依存配列[]を指定します。
1 2 3 | useEffect(() => { console.log('副作用関数が実行されました!') },[]) |
副作用関数を実行したいタイミングを制御してみます、下記の場合はcountに変化があったときだけ副作用関数を実行します。
1 2 3 4 | const [count, setCount] = useState(0) useEffect(() => { console.log(`${count}回クリックされました`) },[count]) |
この場合、再レンダリングが行われてもcountの値に変更がなければ副作用関数は実行されません。
useLayoutEffect
ReactのHookにはuseEffectと似た名前でuseLayoutEffectというフックがあります。useEffectとuseLayoutEffectは使い方、記述方法については似ているのですが大きな違いがあります。useEffectは上記の通り、一度画面が描写された後(レンダリング後)にuseEffectの副作用関数が実行されます。useLayoutEffectは画面が描写される前(レンダリング前)にuseLayoutEffectの中の処理が実行されます。
useCallback
useCallbackはパフォーマンス向上のためのフックで、メモ化したコールバック関数を返します。
useEffectと同じように、依存配列の要素のいずれかが変化した場合のみ、メモ化した値を再計算します。
メモ化とは同じ結果を返す処理について、初回のみ処理を実行記録しておき、値が必要となった2回目以降は、前回の処理結果を計算することなく呼び出し値を得られるようにすることです。
1 2 3 | const handleClick = useCallback((e: React.MouseEvent) => { console.log("clicked!"); }, []); |
useCallbackは、初回の呼び出しでは渡された関数をそのまま返します。Appが再レンダリングされたとき、useCallbackの返り値としては初回レンダリング時のときの関数オブジェクトが再利用されます。 つまり、ここでいうhandleClickは初回のレンダリング時も2回目のレンダリング時も同じ(===の意味で等しい)関数オブジェクトになります。 useCallbackを噛まさない場合は、handleClickは毎回新しく作られた関数オブジェクトとなってしまいます。
ここでは、単にログを吐いているだけですが、APIの接続や複雑な計算処理などパフォーマンスに影響がある処理の場合に効果を発揮します。
useContext
useContextとは、Context機能をよりシンプルに使えるようになった機能です。
親からPropsで渡されていないのに、Contextに収容されているデータへよりシンプルにアクセスできるというものです。
createContextでContextを作成します。
<Context.Provider value=<value>>でラップした配下のComponent内ではContextの値(value)を呼び出せるようになります。
1 2 3 4 5 6 7 8 9 10 11 12 | import React, { createContext, useState } from 'react'; export const CountContext = CreateContext(); const [count, setCount] = useState(0); const addCount = () => { setCount(count + 1); }; <CountContext.Provider value={{count, addCount}}> <App /> </CountContext.Provider> |
Contextの値の呼び出しはuseContextを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 | export const App = () => { // プロバイダーに渡した値を呼び出す const {count, addCount} = useContext(CountContext) return ( <div> <p>You clicked {count} times</p> <button onClick={addCount}> Click me </button> </div> ); } |
これだけでContext値を取得できるようになります。
さいごに
React初心者としては、まずhookを使いこなすことが大事だと思いました。基礎を理解してどんどん開発の応用を効かせられるようにしていきたいと思います。