こんにちは!
Reactを使ってWebアプリケーションを作っていると、パフォーマンスの問題に直面することがありますね。
特に、複雑な計算や大量のデータを扱う場合、アプリの動作が遅くなることがあります。
そんなときに役立つのが、ReactのuseMemo
フック。
useMemo
は、計算結果を記憶しておく機能です。
簡単に言えば、同じ計算を何度も繰り返さないようにする賢い方法なんです。
これを使うと、アプリの動作が速くなることがあります。
でも、すべての場面でuseMemo
を使えばいいというわけではありません。
使い方を間違えると、かえってパフォーマンスが悪くなることもあるんです。
だからこそ、正しい使い方を学ぶことが大切なんですね。
この記事では、useMemo
の基本から実践的な使い方まで、順を追って説明していきます。
Reactを勉強し始めたばかりの方でも理解できるよう、なるべくわかりやすい言葉で解説していきますね。
この記事を読めば、以下のようなことがわかるようになります。
useMemo
フックの基本的な使い方- パフォーマンス改善にどう役立つのか
- 実際のコード例を通じた活用方法
- 使用する際の注意点
React環境がない方はこちらも参考にしてください。
![【たった1分】React×Vite×TypeScriptで高速ビルド環境を構築する方法](https://nakamuuu.blog/wp-content/uploads/2024/05/【たった1分】React×Vite×TypeScriptで高速ビルド環境を構築する方法-320x180.png)
useMemoとは?
useMemo
は、Reactのフックの1つです。
フックって聞くと難しそうに感じるかもしれませんが、簡単に言えば「特別な機能を使うためのおまじない」みたいなものです。
useMemo
の主な役割は、計算結果を記憶しておくことです。
これって、どういう意味なのでしょうか?
例えば、複雑な計算をする関数があったとします。
普通なら、その関数は呼び出されるたびに計算を実行します。
でも、useMemo
を使うと、一度計算した結果を覚えておいて、同じ条件なら前回の結果をそのまま使い回してくれるんです。
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
ここで、computeExpensiveValue
は時間のかかる計算をする関数です。
[a, b]
の部分は「依存配列」と呼ばれ、この値が変わったときだけ計算をやり直します。
これを使うと、どんなメリットがあるのでしょうか?
まず、無駄な計算を減らせるので、アプリの動作が速くなります。
特に、データが大量にある場合や、複雑な計算をする場合に効果を発揮します。
useMemoの使用シーン
useMemo
はパワフルなツールですが、どんな場面で使えば効果的なのでしょうか?
ここでは、useMemo
が特に役立つ2つの主要な使用シーンを見ていきましょう。
計算コストの高い処理
1つ目は、時間のかかる計算を行う場合です。
例えば、大量のデータを扱うときや、複雑な数学的計算を行うときがこれに当たります。
具体的な例を挙げてみましょう。
1万件のユーザーデータがあって、その中から特定の条件に合うユーザーを探す処理を考えてみてください。
こんな感じのコードになるでしょう:
const filteredUsers = useMemo(() => {
return users.filter(user => user.age > 30 && user.isActive);
}, [users]);
この場合、users
データが変わらない限り、フィルタリング処理は一度だけ実行されます。
データが大量にある場合、これだけでもかなりの時間短縮になりますね。
子コンポーネントへの最適化
2つ目は、子コンポーネントに渡すデータの最適化です。
Reactでは、親コンポーネントが再レンダリングされると、その子コンポーネントも再レンダリングされます。
でも、渡すデータが変わっていないのに再レンダリングするのは無駄ですよね。
こんな場合にuseMemo
が役立ちます:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
return (
<ChildComponent value={memoizedValue} />
);
こうすることで、a
やb
が変わらない限り、ChildComponent
は不要な再レンダリングを避けられます。
ただし、すべての props にuseMemo
を使う必要はありません。
計算コストが低い場合は、普通に値を渡す方が効率的なこともあります。
useMemoを実際に動かしてみる
さて、ここからはuseMemo
の実践的な使用例を見ていきましょう。
具体的なコードを通じて、useMemo
がどのように役立つのか、そしてどのように使うのかを学んでいきます。
フィボナッチ数列の計算を例に取ってみます。
フィボナッチ数列は、計算に時間がかかる典型的な例です。
import { useState, useMemo } from "react";
function FibonacciCalculator() {
const [inputNum, setInputNum] = useState<string>("10");
const [calcNum, setCalcNum] = useState<number>(10);
const fibonacci = useMemo(() => {
if (Number.isNaN(calcNum)) return null;
const fib = (n: number): number => {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
};
console.log("フィボナッチ数を計算中...");
return fib(calcNum);
}, [calcNum]);
const handleCalculate = () => {
const num = parseInt(inputNum);
if (!isNaN(num)) {
setCalcNum(num);
}
};
return (
<div>
<input
type="number"
value={inputNum}
onChange={(e) => setInputNum(e.target.value)}
/>
<button onClick={handleCalculate}>計算</button>
<p>
フィボナッチ数({calcNum}):{fibonacci}
</p>
</div>
);
}
export default FibonacciCalculator;
import ReactDOM from "react-dom/client";
import FibonacciCalculator from "./FibonacciCalculator.tsx";
ReactDOM.createRoot(document.getElementById("root")!).render(
<FibonacciCalculator />
);
この例では、useMemo
を使ってフィボナッチ数を計算しています。
入力値が変わらない限り、計算結果はメモ化されて再利用されます。
実際にこのコンポーネントを使用すると、同じ数値で複数回計算ボタンを押しても、コンソールログは1回しか表示されないはずです。
これがuseMemo
によるメモ化の効果です。
数値を変更して計算ボタンを押すと、新しい計算が行われ、結果が更新されます。
この例を通じて、useMemo
が重い計算の最適化にどのように役立つか、より実感できるのではないでしょうか。
useMemoを使用する際の注意点
useMemo
は強力なツールですが、適切に使用しないと思わぬ問題を引き起こす可能性があります。
ここでは、useMemo
を使用する際の重要な注意点について説明します。
過剰な最適化を避ける
useMemo
を使用すると、確かにパフォーマンスが向上する場合がありますが、すべての場所で使用すべきではありません。
過剰な最適化は、かえってアプリケーションの複雑さを増し、メンテナンスを難しくする可能性があるんです。
以下のような場合は、useMemo
の使用を避けた方が良いでしょう:
単純な計算や軽い処理
例えば、配列の長さを取得するだけなら、useMemo
は不要です。
// 良くない例
const arrayLength = useMemo(() => array.length, [array]);
// 良い例
const arrayLength = array.length;
プリミティブ値の生成
文字列や数値などの単純な値を生成する場合も、useMemo
は過剰です。
// 良くない例
const greeting = useMemo(() => `こんにちは、${name}さん`, [name]);
// 良い例
const greeting = `こんにちは、${name}さん`;
依存配列の正しい使用
useMemo
の依存配列は非常に重要です。
正しく設定しないと、期待通りの動作をしない可能性があります。
必要なすべての依存関係を含める
計算に使用するすべての変数を依存配列に含めましょう。
// 良くない例(ageが変更されても再計算されない)
const userInfo = useMemo(() => `${name}(${age}歳)`, [name]);
// 良い例
const userInfo = useMemo(() => `${name}(${age}歳)`, [name, age]);
不要な依存関係を含めない
計算に関係のない値を依存配列に含めると、不要な再計算が発生します。
// 良くない例(unrelatedValueが変更されるたびに再計算される)
const expensiveResult = useMemo(() => expensiveCalculation(a, b), [a, b, unrelatedValue]);
// 良い例
const expensiveResult = useMemo(() => expensiveCalculation(a, b), [a, b]);
関数を依存配列に含める場合の注意
関数を依存配列に含める場合、その関数が再生成されないよう注意が必要です。
useCallback
と組み合わせて使用するのが一般的です。
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
const memoizedResult = useMemo(() => {
return expensiveComputation(memoizedCallback);
}, [memoizedCallback]);
適切な場所で適切に使用することが、useMemo
を効果的に活用するコツです。
過剰な最適化は避け、本当に必要な場所でのみ使用しましょう。
そして、依存配列の設定には細心の注意を払いましょう。
これらの注意点を守ることで、useMemo
を効果的に使用し、アプリケーションのパフォーマンスを向上させることができます。
useCallbackとの違い
Reactを学んでいると、useMemo
と似たような機能を持つuseCallback
というフックに出会うことがあります。
この2つは似ているようで異なる用途があります。
ここでは、useMemo
とuseCallback
の違いを明確にし、それぞれをどのような場面で使うべきかを説明します。
基本的な違い
useMemo
は値をメモ化するのに対し、useCallback
は関数自体をメモ化します。
これが最も重要な違いです。
useMemo
:計算結果(値)をメモ化useCallback
:関数自体をメモ化
例えば、以下のように使います:
// useMemoの例
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
// useCallbackの例
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
使用する場面の違い
それぞれのフックは、異なる場面で活躍します。
- 計算コストの高い処理の結果をメモ化する場合
- オブジェクトや配列を生成し、それを子コンポーネントにpropsとして渡す場合
- イベントハンドラ関数を子コンポーネントにpropsとして渡す場合
- 依存配列に含まれる関数を
useEffect
などの他のフックで使用する場合
パフォーマンスへの影響
両方のフックはパフォーマンス最適化のために使用されますが、その効果は状況によって異なります。
useMemo
は計算結果をメモ化するため、重い計算を避けるのに有効です。useCallback
は関数の再生成を防ぐため、子コンポーネントの不要な再レンダリングを避けるのに有効です。
ただし、どちらのフックも使用にはコストがかかります。
メモ化自体にも処理時間とメモリが必要なので、軽い処理や単純な関数には使用を避けた方が良いでしょう。
使い分けのポイント
- 計算結果をメモ化したい場合は
useMemo
- 関数自体をメモ化したい場合は
useCallback
- 子コンポーネントに渡すpropsが頻繁に変わる場合、適切な方を選択
useEffect
の依存配列に関数を含める場合はuseCallback
を検討
結局のところ、useMemo
とuseCallback
はどちらも最適化のためのツールです。
適切な場面で適切に使うことが大切です。
過剰な最適化は避け、本当に必要な場所でのみ使用するよう心がけましょう。
これでuseMemo
とuseCallback
の違いが理解できたのではないでしょうか。
次の章では、これまでの内容をまとめ、useMemo
の使用に関する最終的なアドバイスを提供します。
ひとつひとつ真摯に向き合う企業
![ONE_WEDGE社員募集](https://nakamuuu.blog/wp-content/uploads/2024/03/IMG_5705_Image-Enhancer.jpg)
株式会社 ONE WEDGEでは、新たな仲間を募集しています!
私たちと一緒に、革新的で充実したキャリアを築きませんか?
当社は、従業員が仕事と私生活のバランスを大切にできるよう、充実した福利厚生を整えています。
- 完全週休2日制(土日休み)で、祝日や夏季休暇、年末年始休暇もしっかり保証!
- 様々な休暇制度(有給、慶弔、産前・産後、育児、バースデー休暇)を完備!
- 従業員の成長と健康を支援するための表彰制度、資格取得支援、健康促進手当など!
- 生活を支えるテレワーク手当、記事寄稿手当、結婚祝金・出産祝金など、様々な手当を提供!
- 自己啓発としての書籍購入制度や、メンバー間のコミュニケーションを深める交流費補助!
- 成果に応じた決算賞与や、リファラル採用手当、AI手当など、頑張りをしっかり評価!
- ワークライフバランスを重視し、副業もOK!
株式会社 ONE WEDGEでは、一人ひとりの従業員が自己実現できる環境を大切にしています。
共に成長し、刺激を与え合える仲間をお待ちしております。
あなたの能力と熱意を、ぜひ当社で発揮してください。
ご応募お待ちしております!
ホームページ、採用情報は下記ボタンからご確認ください!
応募、ご質問など、LINEでお気軽にご相談ください♪
まとめ
- 基本機能
useMemo
は計算結果をメモ化し、不要な再計算を防ぎます。- 主な使用シーン
- 計算コストの高い処理
- 大量データの加工
- 子コンポーネントへのprops最適化
- 注意点
- 過剰な使用は避ける
- 依存配列を正しく設定する
- 軽い処理には不要
- 使い方のコツ
- パフォーマンス問題が実際に発生してから使用を検討
- React Developer Toolsなどで計測しながら最適化
useMemo
は、Reactアプリケーションのパフォーマンスを向上させる強力なツールです。
しかし、useMemo
は万能薬ではありません。
適切な場面で適切に使うことが重要です。
パフォーマンスと可読性のバランスを取りながら、必要な場所で効果的に使用しましょう。