banner
我是老王

我是老王

我用尽全力,过着平凡的生活!
github
twitter
email
follow
discord user

Reactパフォーマンス最適化 | もうあなたのReactページをPPTのようにカクカクさせないで!useMemoは必須です

React プロジェクトをやったことがある人は、こんな状況に遭遇したことがあるでしょう:開発中はページがスムーズに動くのに、データ量が増えるとカクカクになってしまう。ボタンをクリックするのに 3 秒待たされる、うちの猫が起きるより遅い。

すぐにバックエンドのせいにしないでください。今日は React でよく見落とされがちだけど、とても役に立つものについて話します —— useMemo

この名前は「記憶がある」ように聞こえますが、実際にはコンポーネントの省エネモードです。

useMemo とは#

あなたに同僚がいると想像してください。複雑な質問をするたびに、彼は計算に時間がかかります。重要なのは、毎回質問するたびに彼は再計算を行うことです。データが全く変わっていなくても。

useMemoはこの同僚に記憶を持たせたようなものです:前回計算した結果を覚えているので、直接使ってもいいですか?

本質的には計算結果をキャッシュすることで、依存関係が変わらなければ古い結果をそのまま返し、再計算を避けます。

構文はこんな感じです:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

aまたはbが変わったときだけ再計算され、それ以外は前回の結果をそのまま返します。

いつ使うべきか#

1. 計算が重いとき#

例えば、5000件の注文データを処理してソート、フィルタリング、集計する場合。このような操作は毎回ファンが回り始めるほど重く、コンポーネントは一日に何十回もレンダリングされます。

const processedData = useMemo(() => {
  return heavyProcess(orders); // 時間がかかる操作
}, [orders]); // ordersが変わったときだけ再計算

これにより、毎回のレンダリングで計算するのではなく、1 回だけ計算することになります。

2. 子コンポーネントにオブジェクトや配列を渡すとき#

子コンポーネントがReact.memoを使っているのに、常に再レンダリングされる?それは渡される prop が毎回新しい参照になっている可能性が高いです。

例えば、こんな感じ:

// 毎回レンダリングで新しい配列を作成、内容が同じでも
<MyComponent filters={[{ type: "active" }]} />

解決方法:

const stableFilters = useMemo(() => [{ type: "active" }], []);
<MyComponent filters={stableFilters} />;

これでオブジェクトのアドレスが変わらず、React.memoが正常に機能します。

3. 他の Hook の依存項目として使うとき#

const config = { userId, theme };

useEffect(() => {
  fetchUserData(config);
}, [config]); // 問題が発生します!

毎回のレンダリングでconfigは新しいオブジェクトになり、useEffectが繰り返しトリガーされます。

解決策:

const config = useMemo(() => ({ userId, theme }), [userId, theme]);

useEffect(() => {
  fetchUserData(config);
}, [config]);

これでuserIdまたはthemeが変わったときだけconfigが更新されます。

useMemo vs useCallback#

この 2 つは混同しやすいです:

Hookキャッシュするもの使用シーン
useMemo1 つの値複雑な計算、オブジェクト / 配列、依存項目として
useCallback1 つの関数そのもの関数の変化による子コンポーネントの再レンダリングを防ぐ
// useMemo: "計算結果"をキャッシュ
const total = useMemo(() => items.reduce(sum), [items]);

// useCallback: "関数そのもの"をキャッシュ
const handleClick = useCallback(() => doSomething(id), [id]);

よくある落とし穴#

依存項目を間違える#

useMemo(() => expensive(), [{}]); // 毎回新しいオブジェクト!
useMemo(() => expensive(), [[]]); // 毎回新しい配列!

依存項目が安定した値であることを確認してください。

useMemo の乱用#

すべての計算をキャッシュする必要はありません。単純なa + bの場合、useMemoを使うと逆に無駄になります。

React の公式も言っています:早すぎる最適化は悪の根源です。まずパフォーマンスのボトルネックを見つけてからuseMemoを使いましょう。

まとめ#

いつ使うべきか:

  • 計算が重いとき
  • memo子コンポーネントに渡すオブジェクト / 配列
  • 他のHookの依存項目として

覚えておいてください:それはスイスアーミーナイフであって、バンドエイドではありません。

ページがカクカクしているからといってすぐにフレームワークを変えないで、まずuseMemoに給料を支払うべきかどうかを考えてみてください。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。