💾

Reactの`state`に大容量データを保存するのは危険?

2024/11/09に公開
2

Reactのstateに大容量データを保存するのは危険?

🔍 調査するに至った経緯

こんにちは。最近、Reactで大容量データを扱うプロジェクトに直面し「大きなデータをReactのstateに保存しても問題ないのか?」と疑問に思いました。PCのメモリには余裕があるのに、なぜReactのstateでデータを持つのは問題だと言われるのか?今回はその疑問を、解決しようと思い記事を書きました。

例えば以下のような状況です。

  • 高解像度の画像データをBase64エンコードしてstateに保持している場合
  • 大量のデータを一度にフェッチして、ページネーションや仮想スクロールを実装せずにそのままリスト表示している場合

💾 Reactのstateに保存できる容量ってどのくらい?

結論から言うと、Reactのstateに保存するデータの容量は数MB以下が理想です。あまりに大きなデータをstateに保存すると、パフォーマンスが悪くなったり、最悪ブラウザがクラッシュしたりすることがあります。

🚫 なぜ大容量データをstateに入れるのはダメなの?

stateに保持するということはメモリにデータを置いている

Reactのstateにデータを入れると、そのデータは ブラウザのメモリ(RAM) に保存されます。これはパソコンの物理メモリを使っており、アプリが動いている間だけ一時的に保持されるものです。stateが変更されるたびに、Reactはそのデータを使って画面を再描画(レンダリング)します。このため、大きなデータを保持していると、再描画に時間がかかり、アプリの動作が遅くなります。

また、ブラウザが使えるメモリの量には限界があります。パソコン自体のメモリに余裕があっても、ブラウザは安全性や他のタブとのバランスを考えてメモリの使用を制限します。そのため、大容量データをそのままstateに保存するのはリスクが高く、アプリが重くなる原因になります。

localStorageIndexedDBはそうではない

localStorageIndexedDBは、 メモリではなくストレージ(ディスクに近い保存場所) にデータを保存します。これは、ブラウザを閉じてもデータが消えないため、長期的な保存に向いています。

  • localStorageは小さなデータを保存するのに適しており、容量の制限が厳しい(通常は数MB程度)ため、大容量のデータには向いていません。
  • 一方、IndexedDBは非同期で動作し、大容量データ(数百MB〜GB)でも扱えるため、大きなデータを保存する場合に適しています。

⚠️ PC自体のメモリに余裕があってもたくさん使っていいわけではない

PCに物理的なメモリがたくさんあっても、ブラウザはそのメモリを無制限に使うことができません。ブラウザには独自のメモリ使用制限があり、1つのウェブページが大量のメモリを使用すると、他のページやシステム全体のパフォーマンスに影響を及ぼす可能性があるからです。そのため、Reactのstateに大きなデータを保存すると、アプリが重くなったり、最悪の場合ブラウザがクラッシュする原因になります。

❓ メモリに関する具体的な疑問と回答

ここで、皆さんが抱きそうな具体的な疑問を一つ紹介します。

🗑️ JavaScriptのメモリ管理とガベージコレクション

JavaScriptは、メモリ管理にガベージコレクションという仕組みを使っています。ガベージコレクションとは、使われなくなったメモリを自動的に解放する仕組みです。しかし、ガベージコレクションが動くタイミングはJavaScriptエンジンによって決まるため、制御することはできません。

例えば、大きなデータをstateに保持していると、そのデータが不要になったときにガベージコレクションが適切に動作しないと、一時的にメモリが解放されずにメモリリーク(メモリが無駄に使われたままになる現象)が発生する可能性があります。特に、頻繁にデータが更新される場合は、ガベージコレクションが追いつかず、アプリのパフォーマンスが低下することがあります。

このため、Reactで大容量データを扱う際は、ガベージコレクションの影響も考慮し、必要なデータだけをstateに保持することで、メモリ使用量を抑えることが重要です。

💡 じゃあ、どうやって大容量データを扱うの?

大容量のデータを扱う際は、すべてをstateに保存せず、以下のような方法を取るのが良いです。

1. 必要な部分だけを保存する

すべてのデータをstateに入れるのではなく、必要な部分だけをロードしてstateに保持します。例えば、ページごとにデータを分けて少しずつ表示したり、ユーザーが操作したときに必要な分だけ読み込んだりすることで、メモリの負担を減らせます。

2. IndexedDBを活用する

IndexedDBというブラウザの中のデータベースを使う方法があります。これは大容量データを保存するのに適していて、ブラウザを閉じてもデータが消えないという特長があります。大きなデータはIndexedDBに保存しておき、必要なときだけそこから読み込むようにすれば、stateを軽く保てます。

3. localStorageは小さいデータ向き

localStorageもデータを保存できますが、容量が少なく、小さな設定情報などを保存するのに適しています。大量のデータには向いていないので、stateの代わりに使う場合は注意が必要です。

✅ まとめ

Reactのstateには、 できる限り小さなデータ(数MB以下) を保存するのがポイントです。大容量データが必要な場合は、IndexedDBやバックエンドのデータベースと連携し、stateには必要な部分だけを保持するようにしましょう。

まずはstateには画面に表示するための最小限のデータだけを入れることを意識してみてください。そうすることで、アプリのパフォーマンスが良くなり、ユーザーにも快適な体験を提供できます。

ぜひ今回の内容を活かして、効率的なデータ管理を目指してみてくださいね!

株式会社くりぼー

Discussion

YutaUraYutaUra

すみません。純粋な疑問なのですが、Reactのステートに数MB以上のデータが入る状況ってどんな状況を想定していますか?

数MBってかなりでかいと思うので、具体例がないと特に初期学者向けの記事なら少しミスリードになってしまいそうだと思いました💦

株式会社くりぼー株式会社くりぼー

コメントありがとうございます!
確かに、一般的な開発ではstateに数MB以上のデータを入れることは少ないです。

例えば以下のようなケースで想定しました。

  • 高解像度の画像データをBase64エンコードしてstateに保持している場合
  • 大量のデータを一度にフェッチして、ページネーションや仮想スクロールを実装せずにそのままリスト表示している場合

これらの具体例を記事に追記し、読者の方々がイメージしやすいように改善してみます。
貴重なご意見ありがとうございました。