セレクタは状態から特定のデータを読み出す(導出する)関数です。メモ化はセレクタの結果をキャッシュするため、入力が変わるときだけ再計算されます — セレクタが高コストな処理を行う場合、または不要な再レンダリングを避けるために重要です。
基本的なセレクタ — 状態アクセスをカプセル化
= state => state.;
= state => state..;
= state =>
state...( sum + i., );
セレクタは状態構造の知識を一元化します — コンポーネントは selectCartTotal(state) を呼び出すだけで、どこにどのように保存されているかを知る必要がありません。そのため、状態の形が変わった場合は、1つのセレクタを更新するだけで済み、すべてのコンポーネントを変更する必要はありません。
const selectExpensiveList = state =>
state.items.filter(i => i.active).sort(compareFn); // runs EVERY time, even if items didn't change
新しい配列やオブジェクトを作成するセレクタは、呼び出すたびに新しい参照を返します — これは不要な再レンダリング(React は「新しい」値と見なす)をトリガーし、計算を無駄にします。
import { createSelector } from "reselect"; // or RTK's createSelector
const selectActiveSorted = createSelector(
[state => state.items], // input selector(s)
(items) => items.filter(i => i.active).sort(compareFn) // recompute ONLY if items changed
);
createSelector は結果をキャッシュし、入力(state.items)が実際に変わったときだけ高コストな計算を再実行します — そうでなければ、同じ参照を返すため、再計算と下流の再レンダリングの両方を防ぎます。
const selectTotal = createSelector(
[selectActiveSorted, selectTaxRate], // build on other selectors
(items, rate) => items.reduce((s, i) => s + i.price, 0) * (1 + rate)
);
セレクタは合成でき、シンプルで個別にキャッシュされるピースから複雑な導出を構築します。
セレクタはコンポーネントを状態の形から分離します(保守性の向上)し、導出データを表現する場所を提供します。
メモ化により、導出セレクタが効率的になります — 反復的な高コスト計算を回避し、特に重要なことに、安定した参照を返すため、接続されたコンポーネントが不要に再レンダリングされません。
Redux/NgRx アプリケーションでは、メモ化されたセレクタ(Reselect/createSelector)はパフォーマンスとアーキテクチャの重要なツールです。同じキャッシング概念は、他の場所では useMemo や computed として現れます。