React Hooks、なんとなく既存のコードを見てふんわり使っていることが多いので
使用頻度の高いきちんと調べてみました。
React Hooksの種類
名前 | 効果 | 対象 | 使用目的 |
useEffect | 処理の実行 | いろいろ | レンダリング終了後に処理を実行したいとき |
memo | メモ化 | コンポーネント | 再レンダリング時の子コンポーネント再生成回避 |
useCallBack | メモ化 | 関数 | 再レンダリング時の関数再生成回避 |
useMemo | メモ化 | 変数 | 再レンダリング時に変数を保持、再利用したいとき |
useState | 状態管理 | 画面上変化する値を管理する | |
useRef | 状態管理 | 画面上以外でも変化する値を管理する |
おおまかにこんな感じになります。
基本的には、不要なレンダリングを減らしてUXを向上するのが目的になります。
再レンダリングが起きる条件
再レンダリングを回避するためには、再レンダリングが起きる条件を把握する必要があります。
再レンダリングが起きるのは以下の3つのパターンです
- stateが更新されたコンポーネント
- propsが変更されたコンポーネント
- 再レンダリングされたコンポーネント配下のコンポーネントすべて
useMemo
useMemoは変数をメモ化し、計算結果をします。
第二引数に値を渡すと、その値が変化したときにだけ再計算します。
const ids = useMemo(() => state.fileter((v) => v.id), [state]);
レンダリング中にも実行でき、jsxを返すこともできるので
stateによってDOMの構成事態を変えたい時も使えて便利です。
const render = useMemo(() =>
(
<div>{state}</div>
) ,[state]
);
memo
react.memoはコンポーネントをメモ化します。
コンポーネントに渡されるpropsの値に変化がない場合に、コンポーネントのレンダーをスキップすることができます。
const MyComponent = React.memo(function MyComponent(props) {
/* render using props */
});
componentを外だししている場合には下記のように書けます。
function MyComponent(props: myProps) {}
////
export default memo(MyComponent);
useCallBack
useCallBackは関数をメモ化します。
useMemoと同様に第二引数に指定した値の配列の要素のいずれかが変化したときに、関数を再生成します。このタイミングでは関数は実行されません
コールバックで使われている引数は、依存配列に格納するようにしてください。
でないと、引数1は更新した値で引数2は初期値で関数が実行され、結果が不正になります。
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
useEffect
useEffectは、引数を指定しないと初回のレンダリング完了後、および再レンダリングのたびに実行されます。
useEffect(() => {
document.title = `You clicked ${count} times`;
});
第二引数を設定することで、再レンダリングをスキップすることができます。
第二引数に空の配列をセットすることで、初回のレンダリング後のみ実行されます。
useEffect(() => {
initilize();
}, []);
第二引数に変数をセットすると、引数に変化があったときだけ実行します。
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes
ちなみに、アンマウント時の処理にも使えます。
useEffect(() => {
initilize();
return()=>{
unMount();
}
}, []);
useRef
useRefは、useStateと似ていますが、画面上の変化がなくても値の変化を保持できます。
裏で状態変化を監視しておきたい時に便利です。
値のセットは ref.current=”” の形で行います。
const flg= useRef<boolean>(false);
useEffect(()=>{
if(state){
flg.current = true
}
},[state])
useState
useStateは画面上変化する値を保持してくれます。
値のsetはsetState(“”)の形で行います。
const [state,setState] = useState("");
setState("hoge")
ちなみに、すぐにsetStateができない場合があるので
oldを差分を取得しておくと確実に値をセットできるらしいです!
const newUser = [];
setLocalUsers((old) =>
old.map((p, pIdx) => (pIdx === idx ? newUser : p)),
);
まとめ
特に使い方が難しいのはuseEffectとuseMemoの使い分けだと思います。
useEffectはレンダリング終了後、useMemoはレンダリング中も動くという特徴があるので
うまく使い分けないとレンダリングが間に合わなくて…という事態になります。
また、useRefとuseStateもリアクティブな値を保持するうえで共通していますが、useStateはユーザが操作する値、useRefは裏で持っておく値という区別をして使い分けていきたいです。