<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>メモ化</title>
	<atom:link href="https://techgrowup.net/tag/%E3%83%A1%E3%83%A2%E5%8C%96/feed/" rel="self" type="application/rss+xml" />
	<link>https://techgrowup.net</link>
	<description>エンジニアを強くする</description>
	<lastBuildDate>Wed, 30 Apr 2025 23:00:00 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://techgrowup.net/wp-content/uploads/2021/05/hp-icon-150x150.png</url>
	<title>メモ化</title>
	<link>https://techgrowup.net</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>useMemo徹底ガイド──Reactアプリの再計算コストを劇的に減らす最適化テクニック</title>
		<link>https://techgrowup.net/react-usememo/</link>
					<comments>https://techgrowup.net/react-usememo/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[techgrowup]]></dc:creator>
		<pubDate>Wed, 30 Apr 2025 23:00:00 +0000</pubDate>
				<category><![CDATA[React]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[useCallback]]></category>
		<category><![CDATA[useMemo]]></category>
		<category><![CDATA[パフォーマンス]]></category>
		<category><![CDATA[メモ化]]></category>
		<category><![CDATA[依存配列]]></category>
		<category><![CDATA[再レンダー最適化]]></category>
		<guid isPermaLink="false">https://techgrowup.net/?p=2838</guid>

					<description><![CDATA[useMemoとは何か useMemo は指定した計算式をメモ化（キャッシュ）し、依存配列が変わらない限り再実行をスキップするReactフックです。たとえば数千件のリストを高コストなフィルタリングやソートで描画する場合、 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">useMemoとは何か</h2>



<p class="wp-block-paragraph"><code>useMemo</code> は指定した計算式をメモ化（キャッシュ）し、<strong>依存配列が変わらない限り再実行をスキップ</strong>するReactフックです。たとえば数千件のリストを高コストなフィルタリングやソートで描画する場合、入力が変わらなければ同じ結果を再計算するのはムダです。<code>useMemo</code> を使えば計算を一度だけ行い、次回レンダーではキャッシュ済みの値を返すため描画が高速化します。</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="import { useMemo } from 'react';

function ExpensiveList({ items, query }) {
  const filtered = useMemo(() =&gt; {
    return items.filter(item =&gt; item.name.includes(query));
  }, [items, query]); // itemsかqueryが変わったときだけ再計算

  return filtered.map(item =&gt; &lt;li key={item.id}&gt;{item.name}&lt;/li&gt;);
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> { </span><span style="color: #9CDCFE">useMemo</span><span style="color: #D4D4D4"> } </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;react&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">ExpensiveList</span><span style="color: #D4D4D4">({ </span><span style="color: #9CDCFE">items</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4"> }) {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">filtered</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">useMemo</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">items</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">filter</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">item</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">item</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">name</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">includes</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4">));</span></span>
<span class="line"><span style="color: #D4D4D4">  }, [</span><span style="color: #9CDCFE">items</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">query</span><span style="color: #D4D4D4">]); </span><span style="color: #6A9955">// itemsかqueryが変わったときだけ再計算</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">filtered</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">map</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">item</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">li</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">key</span><span style="color: #D4D4D4">=</span><span style="color: #569CD6">{</span><span style="color: #9CDCFE">item</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">id</span><span style="color: #569CD6">}</span><span style="color: #808080">&gt;</span><span style="color: #569CD6">{</span><span style="color: #9CDCFE">item</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">name</span><span style="color: #569CD6">}</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">li</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<h2 class="wp-block-heading">基本シグネチャ</h2>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="const memoizedValue = useMemo(() =&gt; compute(expensive), [deps]);" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">memoizedValue</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">useMemo</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">compute</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">expensive</span><span style="color: #D4D4D4">), [</span><span style="color: #9CDCFE">deps</span><span style="color: #D4D4D4">]);</span></span></code></pre></div>



<ul class="wp-block-list">
<li><strong>第1引数</strong>：メモ化したい関数（副作用を含まない純粋関数が望ましい）。</li>



<li><strong>第2引数</strong>：依存配列。ここに列挙した値が変わった場合のみ計算し直す。</li>
</ul>



<p class="wp-block-paragraph">依存配列を空配列 <code>[]</code> にするとマウント時に一回だけ実行。<code>undefined</code> を渡すと毎レンダー実行＝メモ化無効なので注意。</p>



<h2 class="wp-block-heading">useMemoが効く典型シナリオ</h2>



<h3 class="wp-block-heading">1. データ変換・重い計算</h3>



<ul class="wp-block-list">
<li>数学的シミュレーションの結果</li>



<li>JSONデータのディープコピーや正規化</li>



<li>Markdown → HTML 変換など CPUコストが高い処理</li>
</ul>



<h3 class="wp-block-heading">2. フィルタ・ソート・検索</h3>



<p class="wp-block-paragraph">リストの要素数が数百〜数千を超える場合、<code>Array.prototype.filter</code> や <code>sort</code> を毎レンダー走らせるとフレーム落ちの原因になります。</p>



<h3 class="wp-block-heading">3. JSX生成コスト削減</h3>



<p class="wp-block-paragraph">巨大リストを map で JSX に展開するとき、その戻り値をメモ化すると描画コストを下げられます（React 18の並列レンダーでも効果的）。</p>



<h2 class="wp-block-heading">useCallbackとの違い</h2>



<figure class="wp-block-table"><div class="scrollable-table"><table class="has-fixed-layout"><thead><tr><th>観点</th><th>useMemo</th><th>useCallback</th></tr></thead><tbody><tr><td>目的</td><td><strong>値</strong>をメモ化</td><td><strong>関数参照</strong>をメモ化</td></tr><tr><td>戻り値</td><td>計算結果そのもの</td><td>メモ化済みの関数</td></tr><tr><td>主要用途</td><td>高コストの計算結果を保持</td><td>子コンポーネントへ渡すハンドラの参照固定</td></tr></tbody></table></div></figure>



<p class="wp-block-paragraph">内部実装では <code>useCallback(fn, deps)</code> は <code>useMemo(() =&gt; fn, deps)</code> と同等です。しかし意味づけが異なるため、値なら <code>useMemo</code>、関数なら <code>useCallback</code> を使うと読みやすくなります。</p>



<h2 class="wp-block-heading">実践シナリオ別コード例</h2>



<h3 class="wp-block-heading">例1：検索フィルタリング</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="function SearchableTable({ rows }) {
  const [keyword, setKeyword] = useState('');
  const visibleRows = useMemo(() =&gt; {
    const lower = keyword.toLowerCase();
    return rows.filter(r =&gt; r.name.toLowerCase().includes(lower));
  }, [rows, keyword]);
  return (
    &lt;&gt;
      &lt;input value={keyword} onChange={e =&gt; setKeyword(e.target.value)} /&gt;
      &lt;ul&gt;{visibleRows.map(r =&gt; &lt;li key={r.id}&gt;{r.name}&lt;/li&gt;)}&lt;/ul&gt;
    &lt;/&gt;
  );
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">SearchableTable</span><span style="color: #D4D4D4">({ </span><span style="color: #9CDCFE">rows</span><span style="color: #D4D4D4"> }) {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> [</span><span style="color: #4FC1FF">keyword</span><span style="color: #D4D4D4">, </span><span style="color: #4FC1FF">setKeyword</span><span style="color: #D4D4D4">] = </span><span style="color: #DCDCAA">useState</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&#39;&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">visibleRows</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">useMemo</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">lower</span><span style="color: #D4D4D4"> = </span><span style="color: #9CDCFE">keyword</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">toLowerCase</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">rows</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">filter</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">r</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">r</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">name</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">toLowerCase</span><span style="color: #D4D4D4">().</span><span style="color: #DCDCAA">includes</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">lower</span><span style="color: #D4D4D4">));</span></span>
<span class="line"><span style="color: #D4D4D4">  }, [</span><span style="color: #9CDCFE">rows</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">keyword</span><span style="color: #D4D4D4">]);</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">input</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">value</span><span style="color: #D4D4D4">=</span><span style="color: #569CD6">{</span><span style="color: #9CDCFE">keyword</span><span style="color: #569CD6">}</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">onChange</span><span style="color: #D4D4D4">=</span><span style="color: #569CD6">{</span><span style="color: #9CDCFE">e</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">setKeyword</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">e</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">target</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">value</span><span style="color: #D4D4D4">)</span><span style="color: #569CD6">}</span><span style="color: #D4D4D4"> </span><span style="color: #808080">/&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">ul</span><span style="color: #808080">&gt;</span><span style="color: #569CD6">{</span><span style="color: #9CDCFE">visibleRows</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">map</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">r</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">li</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">key</span><span style="color: #D4D4D4">=</span><span style="color: #569CD6">{</span><span style="color: #9CDCFE">r</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">id</span><span style="color: #569CD6">}</span><span style="color: #808080">&gt;</span><span style="color: #569CD6">{</span><span style="color: #9CDCFE">r</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">name</span><span style="color: #569CD6">}</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">li</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">)</span><span style="color: #569CD6">}</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">ul</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;/&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  );</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<ul class="wp-block-list">
<li>rows が巨大でも <code>keyword</code> が変わらなければ再計算なし</li>



<li>入力ごとにフィルタされても実用レベルのパフォーマンス</li>
</ul>



<h3 class="wp-block-heading">例2：高コスト画像処理</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="function Preview({ file }) {
  const thumbnail = useMemo(() =&gt; {
    return file ? createThumbnail(file) : null; // Canvas処理など重い関数
  }, [file]);
  return thumbnail ? &lt;img src={thumbnail} /&gt; : null;
}" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">Preview</span><span style="color: #D4D4D4">({ </span><span style="color: #9CDCFE">file</span><span style="color: #D4D4D4"> }) {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">thumbnail</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">useMemo</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">file</span><span style="color: #D4D4D4"> ? </span><span style="color: #DCDCAA">createThumbnail</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">file</span><span style="color: #D4D4D4">) : </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">; </span><span style="color: #6A9955">// Canvas処理など重い関数</span></span>
<span class="line"><span style="color: #D4D4D4">  }, [</span><span style="color: #9CDCFE">file</span><span style="color: #D4D4D4">]);</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">thumbnail</span><span style="color: #D4D4D4"> ? </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">img</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">src</span><span style="color: #D4D4D4">=</span><span style="color: #569CD6">{</span><span style="color: #9CDCFE">thumbnail</span><span style="color: #569CD6">}</span><span style="color: #D4D4D4"> </span><span style="color: #808080">/&gt;</span><span style="color: #D4D4D4"> : </span><span style="color: #569CD6">null</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span></code></pre></div>



<h3 class="wp-block-heading">例3：ソート済みキャッシュ</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="const sorted = useMemo(
  () =&gt; [...items].sort((a, b) =&gt; a.date - b.date),
  [items]
);" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">sorted</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">useMemo</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">  () </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> [...</span><span style="color: #9CDCFE">items</span><span style="color: #D4D4D4">].</span><span style="color: #DCDCAA">sort</span><span style="color: #D4D4D4">((</span><span style="color: #9CDCFE">a</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">b</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">a</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">date</span><span style="color: #D4D4D4"> - </span><span style="color: #9CDCFE">b</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">date</span><span style="color: #D4D4D4">),</span></span>
<span class="line"><span style="color: #D4D4D4">  [</span><span style="color: #9CDCFE">items</span><span style="color: #D4D4D4">]</span></span>
<span class="line"><span style="color: #D4D4D4">);</span></span></code></pre></div>



<p class="wp-block-paragraph">イミュータブルデータならシャローコピーしてソートし、<code>items</code> が同一参照の間は再計算されません。</p>



<h2 class="wp-block-heading">依存配列設計のコツ</h2>



<ol class="wp-block-list">
<li><strong>リストやオブジェクトは参照が変わる条件を把握</strong>
<ul class="wp-block-list">
<li>Redux/Context でステートが再生成されると参照が毎回変わる ⇒ 先に<code>useSelector(shallowEqual)</code>などで固定化</li>
</ul>
</li>



<li><strong>不要な依存を追加しない</strong>
<ul class="wp-block-list">
<li>計算結果に影響しない値を含めると再実行が増える</li>
</ul>
</li>



<li><strong>入れ忘れはバグの温床</strong>
<ul class="wp-block-list">
<li>ESLintの<code>react-hooks/exhaustive-deps</code>ルールを有効化し、自動検出する</li>
</ul>
</li>
</ol>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="// NG: setState関数は安定参照のため依存不要
useMemo(() =&gt; compute(state, setState), [state, setState]); 
// OK
useMemo(() =&gt; compute(state), [state]);" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">// NG: setState関数は安定参照のため依存不要</span></span>
<span class="line"><span style="color: #DCDCAA">useMemo</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">compute</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">state</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">setState</span><span style="color: #D4D4D4">), [</span><span style="color: #9CDCFE">state</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">setState</span><span style="color: #D4D4D4">]); </span></span>
<span class="line"><span style="color: #6A9955">// OK</span></span>
<span class="line"><span style="color: #DCDCAA">useMemo</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">compute</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">state</span><span style="color: #D4D4D4">), [</span><span style="color: #9CDCFE">state</span><span style="color: #D4D4D4">]);</span></span></code></pre></div>



<h2 class="wp-block-heading">パフォーマンス測定と検証</h2>



<h3 class="wp-block-heading">Profiler API</h3>



<ol class="wp-block-list">
<li>React DevTools を開き「Profiler」タブを選択</li>



<li>録画して操作 ⇒ 再計算が走る場所を特定</li>



<li><code>useMemo</code>導入後にレンダー時間が短縮されているか確認</li>
</ol>



<h3 class="wp-block-heading">console.time計測</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="const result = useMemo(() =&gt; {
  console.time('expensive');
  const v = heavy();
  console.timeEnd('expensive');
  return v;
}, [deps]);" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">result</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">useMemo</span><span style="color: #D4D4D4">(() </span><span style="color: #569CD6">=&gt;</span><span style="color: #D4D4D4"> {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">console</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">time</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&#39;expensive&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">v</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">heavy</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">console</span><span style="color: #D4D4D4">.</span><span style="color: #DCDCAA">timeEnd</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&#39;expensive&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">v</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">}, [</span><span style="color: #9CDCFE">deps</span><span style="color: #D4D4D4">]);</span></span></code></pre></div>



<p class="wp-block-paragraph">メモ化の前後で時間を比較し、効果を数字で把握します。</p>



<h2 class="wp-block-heading">よくある落とし穴</h2>



<figure class="wp-block-table"><div class="scrollable-table"><table class="has-fixed-layout"><thead><tr><th>症状</th><th>原因</th><th>対策</th></tr></thead><tbody><tr><td>メモ化しているのに速くならない</td><td>計算自体が軽い／依存が毎回変わる</td><td>メモ化を外す or 依存を安定化</td></tr><tr><td>stale data（古い値を参照）</td><td>依存配列に必要な変数がない</td><td>ESLintルールで検出＋修正</td></tr><tr><td>メモリリーク</td><td>大きな配列・Mapをキャッシュして解放しない</td><td>必要に応じて <code>useMemo</code> を解除</td></tr></tbody></table></div></figure>



<h2 class="wp-block-heading">useMemoを使わない方がいい場合</h2>



<ul class="wp-block-list">
<li><strong>計算コスト &lt; メモ化管理コスト</strong></li>



<li><strong>UIがほぼ静的</strong>：再レンダー回数が少ない</li>



<li><strong>依存が頻繁に変わる</strong>：キャッシュがほぼ活きない</li>
</ul>



<p class="wp-block-paragraph">最適化は「必要になったら測定して導入」が鉄則です。</p>



<h2 class="wp-block-heading"><code>useMemo</code> と Suspense / Concurrent Features</h2>



<p class="wp-block-paragraph">React 18 の並列レンダーでは、<code>useMemo</code>のキャッシュが中断と再開をまたいで保持されるため、長い計算でもUIスレッドをブロックしにくくなっています。<strong>ただしメモ化対象関数は同期的に実行</strong>されるため、CPU負荷の高い処理はWeb Workerや<code>useTransition</code>と組み合わせるとさらに快適です。</p>



<h2 class="wp-block-heading">まとめ</h2>



<p class="wp-block-paragraph"><code>useMemo</code> は</p>



<ol class="wp-block-list">
<li><strong>高コスト計算の結果をキャッシュ</strong>し</li>



<li><strong>依存配列が変わるまで再利用</strong>し</li>



<li><strong>不要な再レンダーを抑制</strong></li>
</ol>



<p class="wp-block-paragraph">というシンプルながら強力な最適化手段です。ただし「とりあえず入れる」は逆効果。まずはプロファイリングでボトルネックを特定し、効果が見込める箇所にのみ導入するのがベストプラクティスです。正しい依存配列と計算粒度を意識し、快適なReact UIを届けましょう。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://techgrowup.net/react-usememo/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Disk: Enhanced  を使用したページ キャッシュ

Served from: techgrowup.net @ 2026-05-25 10:36:35 by W3 Total Cache
-->