MochiuWiki : SUSE, EC, PCB
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Reactの基礎 - React.memoのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Reactの基礎 - React.memo
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == <code>React.memo</code> は、コンポーネントをメモ化するための高階コンポーネント (Higher-Order Component) である。<br> ラップされたコンポーネントは、propsが前回のレンダリング時と変わらない場合に再レンダリングをスキップして、キャッシュされた結果を再利用する。<br> <br> Reactでは、親コンポーネントが再レンダリングされると、子コンポーネントも原則として全て再レンダリングされる。<br> 親が頻繁に状態を更新するが、子コンポーネントのpropsは変化しないケースでは、不必要なレンダリング処理が積み重なりパフォーマンスが低下する。<br> <code>React.memo</code> はこの問題を解消し、propsが変化した場合のみ再レンダリングを実行する。<br> <br> propsの比較には、デフォルトでシャローイコーリティ (浅い比較) が使用される。<br> 比較には <code>Object.is</code> が用いられ、数値・文字列・真偽値等のプリミティブ値は値の同一性で比較される。<br> <r> 一方、オブジェクトや配列は参照の同一性で比較されるため、内容が同じでも毎回新しいオブジェクトを渡すとメモ化が無効化される。<br> <br> このため、<code>React.memo</code> 単独ではなく、<code>useMemo</code> や <code>useCallback</code> と組み合わせることが実践的なパターンとなる。<br> <code>useMemo</code> はオブジェクトや計算結果の参照を安定化し、<code>useCallback</code> は関数の参照を安定化することで、<code>React.memo</code> による比較が正しく機能するようになる。<br> <br> React Compiler (2025年10月 v1.0リリース) は、コンパイル時に自動でメモ化を適用するツールであり、<br> <code>React.memo</code>、<code>useMemo</code>、<code>useCallback</code> の手動記述の必要性を大幅に削減する。<br> <br> ただし <code>React.memo</code> 自体は廃止されず、カスタム比較関数が必要なケース等では引き続き有用である。<br> <br><br> == 基本構文 == TypeScriptにおける <code>memo</code> 関数のシグネチャを以下に示す。<br> <br> <syntaxhighlight lang="typescript"> function memo<P extends object>( Component: React.ComponentType<P>, propsAreEqual?: (prevProps: P, nextProps: P) => boolean ): React.MemoExoticComponent<React.ComponentType<P>> </syntaxhighlight> <br> 下表に、<code>memo</code> 関数の引数の説明を示す。<br> <br> <center> {| class="wikitable" |+ 引数の説明 ! 引数 !! 説明 |- | 第1引数 || ラップするコンポーネント関数を指定する。<br>型パラメータ <code>P</code> にPropsの型を渡すことで型安全になる。 |- | 第2引数 (オプション) || カスタム比較関数 <code>arePropsEqual</code> を指定する。<br><code>true</code> を返すと再レンダリングをスキップし、<code>false</code> を返すと再レンダリングを実行する。<br>省略した場合はデフォルトの浅い比較が使用される。 |} </center> <br> コンポーネントを <code>memo</code> 関数でラップする方法は主に3種類ある。<br> <br> ==== 関数宣言でのラップ ==== 関数宣言を <code>memo</code> でラップするパターンを以下に示す。<br> デバッグ時にコンポーネント名が表示されるというメリットがある。<br> <br> <syntaxhighlight lang="typescript"> import { memo } from 'react'; // コンポーネントのpropsの型定義 interface GreetingProps { name: string; age: number; } // 関数宣言をmemoでラップ const Greeting = memo<GreetingProps>(function Greeting({ name, age }) { return <h1>Hello, {name}! Age: {age}</h1>; });<sup>上付き文字</sup> </syntaxhighlight> <br> ==== アロー関数でのラップ ==== アロー関数を <code>memo</code> でラップするパターンを以下に示す。<br> <br> <syntaxhighlight lang="typescript"> import { memo } from 'react'; // カードコンポーネントのprops型定義 interface CardProps { title: string; content: string; } // アロー関数をmemoでラップ (インラインで定義) const Card = memo<CardProps>(({ title, content }) => { return ( <div className="card"> <h2>{title}</h2> <p>{content}</p> </div> ); }); </syntaxhighlight> <br> ==== Default Exportでのラップ ==== コンポーネント定義とexportを分離するパターンを以下に示す。<br> <br> <syntaxhighlight lang="typescript"> import { memo } from 'react'; // ボタンのprops型定義 interface ButtonProps { onClick: () => void; label: string; } // 通常の関数コンポーネントとして定義 function ActionButton({ onClick, label }: ButtonProps) { return <button onClick={onClick}>{label}</button>; } // 名前を付けてエクスポートしつつ、memoでラップしてメモ化 export default memo<ButtonProps>(ActionButton); </syntaxhighlight> <br><br> == 浅い比較の仕組み == <code>React.memo</code> はデフォルトで <code>Object.is</code> を用いた浅い比較 (Shallow Equality) によってpropsを比較する。<br> <br> ==== プリミティブ値の比較 ==== 数値・文字列・真偽値等のプリミティブ値は、値そのものが比較される。<br> 値が同じであれば <code>Object.is</code> は <code>true</code> を返し、再レンダリングはスキップされる。<br> <br> <syntaxhighlight lang="typescript"> Object.is(3, 3) // true -> 再レンダリングスキップ Object.is("hello", "hello") // true -> 再レンダリングスキップ Object.is(true, true) // true -> 再レンダリングスキップ Object.is(3, 5) // false -> 再レンダリング実行 </syntaxhighlight> <br> ==== オブジェクト・配列の比較 ==== オブジェクトや配列は参照 (メモリアドレス) が比較される。<br> 内容が同一であっても、異なる参照であれば <code>Object.is</code> は <code>false</code> を返し、再レンダリングが実行される。<br> <br> <syntaxhighlight lang="typescript"> Object.is({}, {}) // false -> 再レンダリング実行 (異なる参照) Object.is([], []) // false -> 再レンダリング実行 (異なる参照) const obj = { id: 1 }; Object.is(obj, obj) // true -> 再レンダリングスキップ (同じ参照) </syntaxhighlight> <br> レンダリングのたびに新しいオブジェクトや配列を生成してpropsとして渡すと、<code>React.memo</code> によるメモ化が無効化される。<br> この問題を解消するには、<code>useMemo</code> でオブジェクト参照を安定化するか、個別のプリミティブ値として渡す必要がある。<br> <br><br> == カスタム比較関数 == <code>memo</code> の第2引数にカスタム比較関数を渡すことにより、デフォルトの浅い比較を上書きできる。<br> <br> ==== arePropsEqualの構文 ==== カスタム比較関数のシグネチャを以下に示す。<br> <br> <syntaxhighlight lang="typescript"> (prevProps: P, nextProps: P) => boolean </syntaxhighlight> <br> 戻り値の意味を以下に示す。<br> * <code>true</code> を返す場合 *: propsが同じと判断され、再レンダリングをスキップする。 * <code>false</code> を返す場合 *: propsが異なると判断され、再レンダリングを実行する。 <br> カスタム比較関数を使用する場合は、全てのpropsについて責任を持って比較する必要がある。<br> <br> <u>また、深い等値比較はパフォーマンス低下を招くため、必要な部分のみを比較することが推奨される。</u><br> <br> ==== 使用例 ==== 特定のpropsのみを比較するカスタム比較関数の定義例を以下に示す。<br> <br> <syntaxhighlight lang="typescript"> import { memo } from 'react'; interface UserCardProps { userId: number; name: string; email: string; lastLoginAt: Date; // 毎回新しいDateオブジェクトが渡される可能性がある } // userIdとnameのみを比較し、lastLoginAtの変更では再レンダリングしない function areEqual(prevProps: UserCardProps, nextProps: UserCardProps): boolean { return ( prevProps.userId === nextProps.userId && prevProps.name === nextProps.name && prevProps.email === nextProps.email ); } const UserCard = memo<UserCardProps>(function UserCard({ userId, name, email }) { return ( <div> <p>ID: {userId}</p> <p>名前: {name}</p> <p>メール: {email}</p> </div> ); }, areEqual); </syntaxhighlight> <br><br> == サンプルコード == ==== 基本 ==== 親コンポーネントが頻繁に再レンダリングされる場合でも、<code>React.memo</code> でラップした子コンポーネントはpropsが変化しない限り再レンダリングをスキップする。<br> <br> <syntaxhighlight lang="typescript"> import { memo, useState, FC } from 'react'; interface GreetingProps { name: string; } // memoでラップすることにより、nameが変わらない限り再レンダリングされない const Greeting = memo<GreetingProps>(function Greeting({ name }) { console.log(`Greeting rendered for ${name}`); return <h1>Hello, {name}!</h1>; }); const ParentComponent: FC = () => { const [counter, setCounter] = useState(0); return ( <div> <button onClick={() => setCounter(counter + 1)}> Increment ({counter}) </button> {/* counter が変わっても name="Alice" は変わらないため Greeting は再レンダリングされない */} <Greeting name="Alice" /> </div> ); }; export default ParentComponent; </syntaxhighlight> <br> ==== リストアイテムの最適化 ==== Todoリストのような、多数のアイテムを一覧表示するコンポーネントでは、<code>React.memo</code> と <code>useCallback</code> を組み合わせることが重要である。<br> <code>useCallback</code> を使用しない場合、親コンポーネントが再レンダリングされるたびにコールバック関数の参照が変わり、<code>React.memo</code> によるメモ化が無効化される。<br> <br> <syntaxhighlight lang="typescript"> import { memo, useState, useCallback } from 'react'; interface Todo { id: number; text: string; completed: boolean; } interface TodoItemProps { todo: Todo; onToggle: (id: number) => void; onDelete: (id: number) => void; } // 各Todoアイテムをメモ化する const TodoItem = memo<TodoItemProps>(function TodoItem({ todo, onToggle, onDelete }) { console.log(`TodoItem rendered: ${todo.text}`); return ( <li> <input type="checkbox" checked={todo.completed} onChange={() => onToggle(todo.id)} /> <span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}> {todo.text} </span> <button onClick={() => onDelete(todo.id)}>削除</button> </li> ); }); const TodoList = () => { const [todos, setTodos] = useState<Todo[]>([ { id: 1, text: 'Reactを学ぶ', completed: false }, { id: 2, text: 'TypeScriptを学ぶ', completed: false }, ]); // useCallbackでコールバック関数の参照を安定化する const handleToggle = useCallback((id: number) => { setTodos(todos => todos.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo )); }, []); const handleDelete = useCallback((id: number) => { setTodos(todos => todos.filter(todo => todo.id !== id)); }, []); return ( <ul> {todos.map(todo => ( <TodoItem key={todo.id} todo={todo} onToggle={handleToggle} onDelete={handleDelete} /> ))} </ul> ); }; export default TodoList; </syntaxhighlight> <br> ==== useMemo / useCallbackとの組み合わせ ==== <code>React.memo</code>、<code>useMemo</code>、<code>useCallback</code> の3つを組み合わせたパターンを以下に示す。<br> フィルタリングされた商品リストを表示するコンポーネントを例として用いる。<br> <br> <syntaxhighlight lang="typescript"> import { memo, useState, useCallback, useMemo } from 'react'; interface Product { id: number; name: string; price: number; category: string; } interface FilteredListProps { products: Product[]; onSelect: (product: Product) => void; } // 1. React.memoでコンポーネントをメモ化する const FilteredList = memo<FilteredListProps>(function FilteredList({ products, onSelect }) { console.log('FilteredList rendered'); return ( <ul> {products.map(product => ( <li key={product.id} onClick={() => onSelect(product)}> {product.name} - ${product.price} </li> ))} </ul> ); }); const ProductPage = () => { const [allProducts] = useState<Product[]>([ { id: 1, name: 'Laptop', price: 1200, category: 'Electronics' }, { id: 2, name: 'Keyboard', price: 80, category: 'Electronics' }, { id: 3, name: 'Desk', price: 300, category: 'Furniture' }, ]); const [selectedCategory, setSelectedCategory] = useState('Electronics'); const [searchQuery, setSearchQuery] = useState(''); const [selectedProduct, setSelectedProduct] = useState<Product | null>(null); // 2. useMemoでフィルタリング結果 (配列) の参照を安定化する const filteredProducts = useMemo(() => { return allProducts.filter(product => product.category === selectedCategory && product.name.toLowerCase().includes(searchQuery.toLowerCase()) ); }, [allProducts, selectedCategory, searchQuery]); // 3. useCallbackでコールバック関数の参照を安定化する const handleSelect = useCallback((product: Product) => { setSelectedProduct(product); }, []); return ( <div> <input placeholder="商品を検索..." value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} /> <select value={selectedCategory} onChange={(e) => setSelectedCategory(e.target.value)} > <option value="Electronics">Electronics</option> <option value="Furniture">Furniture</option> </select> {selectedProduct && <p>選択中: {selectedProduct.name}</p>} {/* filteredProducts と handleSelect の参照が安定しているため、 searchQuery等が変わらない限り FilteredList は再レンダリングされない */} <FilteredList products={filteredProducts} onSelect={handleSelect} /> </div> ); }; export default ProductPage; </syntaxhighlight> <br><br> == React Compilerとの関係 == ==== React Compilerによる自動メモ化 ==== React Compiler (旧称: React Forget) は、2025年10月にv1.0がリリースされたBabelプラグインである。<br> コンパイル時にソースコードを解析し、<code>React.memo</code>・<code>useMemo</code>・<code>useCallback</code> に相当する最適化を自動的に適用する。<br> <br> React Compilerを導入することで得られる効果を以下に示す。<br> * メモ化の手動記述が不要になる。 *: <code>useMemo</code> や <code>useCallback</code> を明示的に書かなくても、コンパイラが適切な箇所に自動でメモ化を挿入する。 * コードの簡潔さが向上する。 *: 最適化のためのボイラープレートコードが減少して、ビジネスロジックに集中した記述ができる。 * 段階的な導入が可能 *: 既存プロジェクトに対しても、ファイル単位で段階的に導入できる。 <br> React 19 と React Compilerは別プロジェクトであり、React Compilerの導入はオプションである。<br> React 19を使用していても、React Compilerを導入しない限り自動メモ化は適用されない。<br> <br> ==== React.memoが引き続き必要なケース ==== React Compilerを使用する環境でも、<code>React.memo</code> が有用なケースは存在する。<br> <br> * カスタム比較関数が必要な場合 *: 特定のpropsのみを比較したい場合や、深いネストの一部だけを比較する場合は、カスタム比較関数を持つ <code>React.memo</code> が適している。 *: コンパイラによる自動メモ化はカスタム比較ロジックを持たない。 * React Compilerを導入していないプロジェクト *: React Compilerの導入はオプションであるため、多くの既存プロジェクトでは引き続き手動のメモ化が必要である。 * 明示的な最適化ポイントの文書化 *: チームの方針として、パフォーマンス上重要なコンポーネントを明示的に示したい場合に使用する。 <br><br> == useMemo / useCallbackとの連携 == ==== React.memo単独では不十分なケース ==== <code>React.memo</code> は浅い比較でpropsを評価するため、オブジェクトや関数をpropsとして渡すと参照が毎回変わり、メモ化が無効化される。<br> <br> オブジェクトをpropsとして渡す場合の問題を以下に示す。<br> <br> <syntaxhighlight lang="typescript"> import { memo, useState } from 'react'; interface StyleProps { style: { color: string; fontSize: number }; } const StyledText = memo<StyleProps>(function StyledText({ style }) { console.log('StyledText rendered'); return <p style={style}>テキスト</p>; }); const Parent = () => { const [count, setCount] = useState(0); // 問題: レンダリングのたびに新しいオブジェクトが生成される // memo による比較は常に false になり、毎回再レンダリングされる const style = { color: 'red', fontSize: 16 }; return ( <div> <button onClick={() => setCount(c => c + 1)}>{count}</button> <StyledText style={style} /> </div> ); }; </syntaxhighlight> <br> この問題は、<code>useMemo</code> を使用してオブジェクトの参照を安定化させることで解決できる。<br> <br> <syntaxhighlight lang="typescript"> import { memo, useState, useMemo } from 'react'; const Parent = () => { const [count, setCount] = useState(0); // 解決: useMemo でオブジェクト参照を安定化する const style = useMemo(() => ({ color: 'red', fontSize: 16 }), []); return ( <div> <button onClick={() => setCount(c => c + 1)}>{count}</button> <StyledText style={style} /> </div> ); }; </syntaxhighlight> <br> ==== 3つのメモ化手法の使い分け ==== Reactが提供する3つのメモ化手法の役割と使い分けを以下に示す。<br> <br> <center> {| class="wikitable" |+ 3つのメモ化手法の比較 ! Hook / API !! メモ化の対象 !! 主な用途 |- | <code>React.memo</code> || コンポーネント || propsが変化しない場合に再レンダリングをスキップする。 |- | <code>useMemo</code> || 値 (オブジェクト・配列・計算結果) || 重い計算結果のキャッシュ、オブジェクト参照の安定化 |- | <code>useCallback</code> || 関数 || コールバック関数の参照の安定化 |} </center> <br> 3つの手法は組み合わせて使用することで効果を発揮する。<br> * <code>React.memo</code> でコンポーネントをメモ化する。 *: 子コンポーネントを <code>React.memo</code> でラップして、propsが変わらない場合の再レンダリングを防ぐ。 * <code>useMemo</code> でオブジェクト・配列を安定化する。 *: 親から子へオブジェクトや配列を渡す場合は、<code>useMemo</code> で参照を安定化して <code>React.memo</code> の比較が機能するようにする。 * <code>useCallback</code> で関数を安定化する *: 親から子へコールバック関数を渡す場合は、<code>useCallback</code> で参照を安定化して <code>React.memo</code> の比較が機能するようにする。 <br><br> == 注意事項 == ==== propsにオブジェクトや関数を渡すとmemoが無効化される ==== <code>React.memo</code> を使用していても、以下に示すようなケースではメモ化が無効化される。<br> <br> * レンダリングのたびにインラインでオブジェクトを生成して渡す場合 *: <code>useMemo</code> でオブジェクトをメモ化するか、コンポーネント外で定数として定義することで解決できる。 * レンダリングのたびにアロー関数をインラインで定義して渡す場合 *: <code>useCallback</code> で関数をメモ化することで解決できる。 * propsとして渡すオブジェクトを個別のプリミティブ値に展開する方法 *: オブジェクトをpropsとして渡す代わりに、各プロパティを個別のpropsとして渡すことでも解決できる。 <br> <syntaxhighlight lang="typescript"> // 問題のあるパターン <MemoizedComponent config={{ theme: 'dark', size: 'lg' }} // 毎回新しいオブジェクト onClick={() => handleClick(id)} // 毎回新しい関数 /> // 改善したパターン const config = useMemo(() => ({ theme: 'dark', size: 'lg' }), []); const handleClickMemo = useCallback(() => handleClick(id), [id]); <MemoizedComponent config={config} onClick={handleClickMemo} /> // または個別のプリミティブ値として渡す <MemoizedComponent theme="dark" size="lg" onClick={handleClickMemo} /> </syntaxhighlight> <br> ==== useContextを使用している場合の挙動 ==== <code>React.memo</code> でラップしたコンポーネントが <code>useContext</code> を内部で使用している場合、<br> Contextの値が変更されると <code>React.memo</code> によるメモ化は無効化され、コンポーネントは再レンダリングされる。<br> <br> これは <code>React.memo</code> の仕様上の制限であり、propsが変化していなくてもContextの変更には反応する。<br> この問題を回避するには、Contextを適切に分割して更新頻度の高い値と低い値を別々のContextに分けるか、<code>useContext</code> を使用しない子コンポーネントに分割してpropsとして値を渡すことが有効である。<br> <br> ==== React.memoを使うべきでない場面 ==== <code>React.memo</code> は比較処理のオーバーヘッドを伴うため、全てのコンポーネントに適用すべきではない。<br> 以下に示す場合は使用を避けることが推奨される。<br> <br> * propsがほぼ毎回変わる場合 *: メモ化の効果がなく、比較のオーバーヘッドが増えるだけとなる。 * JSXの生成が軽量なシンプルなコンポーネント *: メモ化のコストが再レンダリングのコストを上回る可能性がある。 * <code>React.memo</code> 単独ではメモ化が機能しない場合 *: オブジェクト・配列・関数をpropsとして渡しており、<code>useMemo</code> や <code>useCallback</code> で参照を安定化していない場合は、<code>React.memo</code> を使っても効果がない。 * <code>useContext</code> を多用している場合 *: Context値の変更で頻繁に再レンダリングが発生して、<code>React.memo</code> の効果が得られにくい。 <br><br> == パフォーマンスの測定 == <code>React.memo</code> の効果を確認するには、React DevTools Profiler または React組み込みの <u>Profiler</u> コンポーネントを使用する。<br> <br> ==== React DevTools Profiler ==== ブラウザ拡張機能のReact DevToolsに内蔵されたProfilerを使用することにより、各コンポーネントのレンダリング時間とレンダリング原因を視覚的に確認できる。<br> <br> 使用手順を以下に示す・ # React DevTools拡張機能をインストールする。 # Webブラウザの開発者ツールを開き、[Profiler]タブを選択する。 # [Record]ボタンを押下して、操作を記録する。 # 停止後、各コンポーネントのレンダリング回数と所要時間を確認する。 <br> ==== Profilerコンポーネント ==== Reactが提供する <u>Profiler</u> コンポーネントをコード内に配置することにより、プログラムからレンダリング情報を取得できる。<br> <br> <syntaxhighlight lang="typescript"> import { Profiler, ProfilerOnRenderCallback, memo, useState } from 'react'; interface GreetingProps { name: string; } const Greeting = memo<GreetingProps>(function Greeting({ name }) { return <h1>Hello, {name}!</h1>; }); const onRenderCallback: ProfilerOnRenderCallback = ( id, // Profilerコンポーネントのid属性 phase, // "mount" (初回) | "update" (再レンダリング) | "nested-update" actualDuration, // 実際のレンダリング時間 (ms) baseDuration, // 最適化なしの推定レンダリング時間 (ms) startTime, // レンダリング開始時のタイムスタンプ commitTime // コミット完了時のタイムスタンプ ) => { console.log(`[Profiler] ${id} (${phase}): ${actualDuration.toFixed(2)}ms (base: ${baseDuration.toFixed(2)}ms)`); }; const App = () => { const [counter, setCounter] = useState(0); return ( <Profiler id="Greeting" onRender={onRenderCallback}> <button onClick={() => setCounter(c => c + 1)}>Increment ({counter})</button> <Greeting name="Alice" /> </Profiler> ); }; export default App; </syntaxhighlight> <br> 下表に、<u>Profiler</u> コンポーネントの主なコールバック引数の説明を示す。<br> <br> <center> {| class="wikitable" |+ ProfilerOnRenderCallbackの引数一覧 ! 引数 !! 型 !! 説明 |- | <code>id</code> || string || <code>Profiler</code> コンポーネントに指定した識別子 |- | <code>phase</code> || string || <code>mount</code> (初回レンダリング)、<code>update</code> (再レンダリング)、<code>nested-update</code> のいずれか |- | <code>actualDuration</code> || number || 今回のレンダリングに要した実際の時間 (ミリ秒) |- | <code>baseDuration</code> || number || メモ化無しで全子コンポーネントをレンダリングした場合の推定時間 (ミリ秒) |- | <code>startTime</code> || number || レンダリング開始時のタイムスタンプ |- | <code>commitTime</code> || number || コミット完了時のタイムスタンプ |} </center> <br> <code>actualDuration</code> が <code>baseDuration</code> より大幅に小さい場合、メモ化が効果的に機能していることを表す。<br> <br><br> == 関連情報 == * [https://react.dev/reference/react/memo React.memo 公式ドキュメント] * [https://react.dev/reference/react/useCallback useCallback 公式ドキュメント] * [https://react.dev/reference/react/useMemo useMemo 公式ドキュメント] * [https://react.dev/learn/react-compiler React Compiler 公式ドキュメント] * [https://react.dev/reference/react/Profiler Profiler コンポーネント 公式ドキュメント] * [[Reactの基礎 - Hooksの基礎]] * [[Reactの基礎 - useState]] * [[Reactの基礎 - useEffect]] * [[Reactの基礎 - useContext]] * [[Reactの基礎 - useCallback]] * [[Reactの基礎 - useMemo]] <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板,React,JavaScript,TypeScript,TSX,memo,React.memo,useMemo,useCallback,メモ化,Memoization,Higher-Order Component,パフォーマンス最適化,浅い比較,Shallow Equality,Object.is,React Compiler,Profiler,再レンダリング |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:Rust]][[カテゴリ:Web]]
Reactの基礎 - React.memo
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse