はじめに
公式ドキュメントを読んでもイマイチuseMemoとuseEffectの違いがわからなかったので少し調べました。
レンダリング回数が違う
レンダリングに関しては以下のようになるみたい
useMemo
- レンダリング中に値が計算されるのでレンダリングは1回
useEffect
- レンダリング後にuseEffectが実行されるのでレンダリングが2回
なので例えば以下のような関数があるとする
function calc(x) { return x + 1 };
この関数の引数に0を入れると初回のレンダリングでは一旦nullが返され、2回目のレンダリングで初めてuseEffectが非同期で実行されて1が返ることになる
import { calc } from "foo";
function useCalc(someNumber: number): number | null {
const [result, setResult] = useState<number | null>(null);
useEffect(() => {
setResult(calc(someNumber));
}, [someNumber]);
return result;
}
useMemoは初回のレンダリングで同期的に値が計算されるので引数に0を入れるとすぐ1が返る
import { calc } from "foo";
function useCalc(someNumber: number): number {
return useMemo(() => {
return calc(someNumber);
}, [someNumber]);
};
なので非同期処理が必要な場合はuseEffectでそうでない場合はuseMemoということになりそうですが、そもそもuseMemoすら必要かどうかも検討する必要がありそう(?)
記事を書きながら浮かんだちょっとした疑問
- udemyのアプリのマイページの画面とかは初回は読み込みでスケルトンが表示されるが、次からはスケルトンなしでコンテンツが表示されるのでそーゆーとこでもメモ化が使われている?
- useEffectでデータフェッチした際に少し遅れて取得されるのは単純にCSRのせいだと思っていたけど、もっというとuseEffectで2回レンダリングされるのが原因?
- もっといいデータ取得方法はある?→SWRというのがあるらしい
おわりに
アルバイトや個人開発ではNextjsを使うのですが、素のReactの理解をもう少し深めたいと思いました。
参考