【入門編】 遅延初期化(Lazy Initialization) – React実践ガイド

こんにちは!Reactの学習、楽しく進められていますか?
画面を自由に動かせるようになってくると、「よし、何かアプリを作ってみるぞ!」とワクワクしてきますよね。

でも、Reactを触り始めたばかりの頃って、次のような不思議な壁にぶつかりがちなんです。

「あれ?画面を再描画(再レンダリング)するたびに、初期値を計算する重い処理が何度も走ってない…?これ、アプリが重くなる原因じゃ…?」

そうなんです。あなたのその直感、大正解!
Reactのコンポーネントは、ボタンをポチポチ押したり文字を入力したりするたびに、何度も何度も「再実行(再レンダリング)」されます。そのときに、毎回重い計算が走っていたら、アプリがカクついてユーザーをイライラさせてしまう原因になってしまいます。

そこで登場するのが、今回お話しする「遅延初期化(Lazy Initialization)」という、ちょっとカッコいい名前のテクニックです。

難しそうに聞こえるかもしれませんが、考え方はとってもシンプル。身近な例えを交えながら、一緒に優しく紐解いていきましょう。「大丈夫ですよ」、ひとつずつ見ていけばすぐに使いこなせるようになりますからね!

—

1. 例え話:遊園地の「最初に1回だけ渡すパスポート」

想像してみてください。あなたは今、大人気の大きな遊園地に遊びに来ました。

ここで、入り口でチケット(パスポート)を発行してもらう場面を思い浮かべてください。
もし、アトラクションに乗るたびに、スタッフさんが「お客さま、最初にお名前と年齢を教えてくださいね!システムで登録しますね!」と、園内に入るたび(あるいはアトラクションに並ぶたび)に一から書類を書かせていたらどうでしょう?

「いやいや、最初に1回入口で登録したんだから、その用紙を使い回してよ!」って思いますよね。

Reactの `useState` もこれと全く同じなんです。

普通に書くと、毎回のレンダリングで「チケット」を作り直してしまう

Reactのコードで、次のような書き方をしたとします。

// 【ちょっと残念な書き方】
// この重い処理、実は画面がパチパチ切り替わる(再レンダリングされる)たびに毎回実行されちゃってます…!
const [state, setState] = useState(重くて時間のかかる初期化処理());

`useState` の中に直接関数や計算式を書くと、Reactは「画面が新しく描画されるたび(=再レンダリングのたび)に、毎回この重い処理をやり直さなきゃ!」と勘違いして、裏でこっそり何度も実行してしまいます。これが、アプリを重くする隠れた原因なんです。

—

2. 遅延初期化(Lazy Initialization)ってなぁに?

そこで、「最初の初回レンダリング(=遊園地の入口)のときだけ、この重い処理を実行して!2回目以降の再レンダリングのときは、計算をスキップして!」とReactにお願いするテクニックが「遅延初期化」です。

やり方は驚くほどカンタン。
`useState` の中に、「関数(アロー関数など)」をそのまま丸ごと渡すだけです。

// 【バッチリな書き方:遅延初期化】
// カッコ () をつけてその場で実行せず、関数そのものを渡す!
const [state, setState] = useState(() => {
// ここに重い計算や、ローカルストレージを読む処理を書く
return 重くて時間のかかる初期化処理();
});

ここでのポイントは、`useState(() => { … })` と書くことで、Reactに対して「ねぇ、最初に必要なときが来るまで、この中の処理を実行しないで(=遅らせて)おいてね。そして、一度計算したら、その結果をずっと大事にとっておいてね」と伝えることなんです。

2回目以降の再レンダリングのとき、Reactはこの関数を実行せず、メモしておいた最初の結果をそのまま使い回してくれます。だから無駄な計算が走らず、アプリがサクサク動くというわけですね!

—

3. 実用的なコードで動きを見てみよう!

百聞は一見にしかず。実際にコードを書いて、コンソール(開発者ツールのログ)にどう表示されるか確かめてみましょう。

以下のコードを、お使いのReact環境(CodeSandboxやViteなど)にそのまま貼り付けて試してみてください。

import React, { useState } from ‘react’;

// 「ものすごく時間がかかる重い計算」をイメージした関数
function getHeavyInitialState() {
console.log(‘🔥【重い処理】初期化の計算が実行されました!(初回のみ走るはず)’);

// 試しに大量のデータを生成するフリ(実際にはローカルストレージの読み込みや複雑な計算など)
let total = 0;
for (let i = 0; i < 1000; i++) { total += i; } return total; } export default function CounterApp() { // ========================================== // ここがポイント!遅延初期化を使っています // ========================================== const [count, setCount] = useState(() => {
return getHeavyInitialState();
});

const [text, setText] = useState(”);

return (

遅延初期化(Lazy Initialization)のサンプル

現在のカウント: {count}

{/ カウントを増やすボタン(画面が再レンダリングされます) /}


文字を入力すると、関係のない再レンダリングが起きます:

setText(e.target.value)}
placeholder=”ここになにか入力してみてね”
/>

);
}

💡 実際に動かして試してみよう!

1. 画面を最初に開いたとき、ブラウザのコンソール画面を見てみてください。
👉 `🔥【重い処理】初期化の計算が実行されました!` というログが1回だけ表示されているはずです。
2. 次に、下のテキストボックスに適当な文字を入力したり、「カウントを増やす」ボタンを何度もポチポチ押してみてください。
👉 画面は何度も再描画されますが、コンソールに `🔥【重い処理】…` のログは二度と流れません!

もし、ここを `useState(getHeavyInitialState())` (関数をその場で実行して渡す書き方)にしてしまうと、テキストボックスに文字を入力するたびに、文字の数だけ毎回あの「重い計算」が走ってしまいます。想像するだけで恐ろしいですよね……!

—

4. どんなときに遅延初期化を使うべき?

すべての `useState` でこれを書く必要はありません。毎回ただの数値(例: `useState(0)`)や、文字列(例: `useState(”)`)をセットするだけなら、JavaScriptにとって一瞬の処理なので、そのまま直書きでOKです。

次のような「ちょっとコストがかかる処理」を初期値にするときに、この遅延初期化を思い出してあげてください。

  • `localStorage` やセッションストレージからデータを読み込んで初期値にするとき

(ブラウザのストレージにアクセスする処理は、地味にCPUに負担がかかります)

  • 大量のデータをループで加工したり、複雑なアルゴリズムで初期値を計算したりするとき
  • 他のモジュールやライブラリを使って、重い初期オブジェクトを生成するとき

—

さいごに

Reactの裏側の動きを知ると、「なんだか難しそう…」と身構えてしまうかもしれませんが、本質はとてもシンプルな思いやりです。

「毎回計算しなくていいものは、最初に1回だけ計算して、あとはスマートに使い回そうね」

現場のプロたちも、パフォーマンスのチューニング(最適化)の基本として、この遅延初期化を自然に使っています。あなたも今日から、`useState` の中にアロー関数を仕込むこのテクニックをマスターできました!

躓きそうになったら、いつでもこの「遊園地のパスポートの例え」を思い出してくださいね。
あなたのReactライフが、もっと楽しく、もっと快適になりますように。それではまた!

コメント

タイトルとURLをコピーしました