はじめに
- useState、useContext以外の重要なフック群。
- useEffectとuseLayoutEffectはコンポーネントのライフサイクルに組み込まれており、特定のタイミングで初期化やアンマウントなどを行える。
- useMemoやuseCallbackはパフォーマンスチューニングで使用する
- ただし、ロジックが複雑になるので乱用はしないこと
- useReducerはuseStateの更新部分を抽象化する。
useEffect
- 副作用となる処理を記述する
- 副作用は描画の一部ではない処理
- コンポーネント描画後に行われるので、非同期処理等(API)
- 依存配列
- 副作用が実行される条件を記述する
- 記載しない場合、再レンダリングの度に実行される
- 空配列の場合、初期描画時のみ実施
- 戻り値
- コールバック関数を返すことで、アンマウント時の処理を行える
useEffect(() => {
console.log('再レンダリング時実行');
});
useEffect(() => {
console.log('初期化時');
return () => console.log('アンマウント時');
}, []);
useEffect(() => {
console.log(`val変更時: ${val}`);
}, [val]);
useLayoutEffect
-
useEffectよりも前に呼び出される
- useEffectは、画面描画後だが、useLayouEffectは画面描画前
- 画面描画前に取得したい情報:画面サイズやマウス座標等を取得する際に利用する
-
以下、マウス座標を取得するフック関数
import { useLayoutEffect, useState } from 'react';
export const useMousePosition = () => {
const [x, setX] = useState(0);
const [y, setY] = useState(0);
const setPosition = ({ x, y }) => {
setX(x);
setY(y);
};
// 初期化時、アンマウント時のイベントリスナー
useLayoutEffect(() => {
window.addEventListener('mousemove', setPosition);
return () => window.removeEventListener('mousemove', setPosition);
}, []);
return [x, y];
};
利用
export const Render = () => {
const [x, y] = useMousePosition();
return (
<>
<span>{`x:${x},y:${y}`}</span>
</>
);
};
useMemo
- 依存配列が配列やオブジェクト等の参照値だった場合、その値を変更しても同一だとみなされず、毎回レンダリングされてしまう。
- その場合、useMemoを使用する
const words = useMemo(() => childeren.split(' '), [childeren]);
useEffect(() => {
console.log('fresh render');
}, [words]);
useCallback
- useMemoと同様の機能で、関数の場合はこちら
// 初期化時のみ
const fn = useCallback(() => {
console.log('function!');
}, []);
useEffect(() => {
console.log('rendaring');
fn();
}, [fn]);
useReducer
- useStateのかわりに使用する。戻り値にstateの初期値と、更新関数を返す。
- stateの更新ロジック定義時に記載することで抽象化できる。
state→reducerへ
// state
-export const Numbers = () => {
- const [number, setNumber] = useState(0);
- // useStateの場合、更新ロジックは使用する際に記載する。
- return <h1 onClick={() => setNumber((number) => number + 1)}>{number}</h1>;
-};
// reducer
+export const Numbers = () => {
+ // reducerの場合、定義時に記載する。
+ const [number, setNumber] = useReducer(
+ (number, newNumber) => number + newNumber,
+ 0
+ );
+ return <h1 onClick={() => setNumber(1)}>{number}</h1>;
+};
フック関数の注意点
- コンポーネント内、またはカスタムフック内で呼び出すこと
- 関数のトップレベルから呼び出す
- 条件文や、ループ、ネストした関数では呼び出さない
- やりたい場合は、フック関数内で行う