0Pricing
React Academy · レッスン

Context Selectorパターン

Contextの一部が変化したときだけ再レンダーするシンプルなselector hookを実装します。

「Context Selectorパターン」はCoddyKit上の無料React Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。

ようこそ

このレッスンでは、コンポーネントをコンテキスト state の一部分だけに購読させる context selector hook を実装し、関係のない部分が変化したときの再レンダリングを防ぎます。

Selector の問題

useContext はコンテキストの ANY の部分が変化すると再レンダリングします。コンポーネントがユーザー名だけを必要としていても、コンテキストに通知リストも含まれている場合、通知を追加すると名前のコンポーネントまで不要に再レンダリングされます。

Selector とは

selector は、大きな state オブジェクトから特定の要素を取り出す関数です。例として `state => state.user.name` があります。selector hook はコンテキストを購読しますが、選択された値が変化した場合にだけ再レンダリングを発生させます。

シンプルな Selector Hook

コンテキストを読み取り、selector の結果を依存値として useMemo でラップする useSelector hook を作成します。選択された値が変化した場合にだけ、コンポーネントが再レンダリングされます。
function useAppSelector(selector) {
  const state = useContext(AppCtx);
  return useMemo(() => selector(state), [state, selector]);
}

// Consumer only re-renders when user.name changes
const name = useAppSelector(s => s.user.name);

浅い等価性チェック

selector と useMemo を使っていても、selector が呼び出されるたびに新しいオブジェクトや配列の参照を返すと再レンダリングされます(例: `s => s.items.filter(...)`)。shallow-equal 比較を使うと、内容が同じ場合に再レンダリングをスキップできます。
import { useRef } from 'react';

function useSelector(selector) {
  const state = useContext(AppCtx);
  const selected = selector(state);
  const ref = useRef(selected);
  if (!shallowEqual(ref.current, selected)) {
    ref.current = selected;
  }
  return ref.current;
}

use-context-selector ライブラリ

本番環境では、**use-context-selector** ライブラリが効率的な購読と等価性チェックに対応した `useContextSelector` hook を提供します。外部の state manager は必要ありません。
import { useContextSelector } from 'use-context-selector';

const name = useContextSelector(AppCtx, s => s.user.name);

Selector に対応したソリューションとしての Zustand

Zustand の `useStore(selector)` hook は selector に標準対応しており、shallow equality も組み込みで利用できます。そのため、細かな購読が重要な大規模な state ツリーに適しています。
const name = useAppStore(state => state.user.name);

Selector が過剰になる場合

コンテキストの更新頻度が低く、コンシューマーの再レンダリングコストも小さい場合、selector は測定可能なメリットなしに複雑さを増やします。まずプロファイリングを行い、必ず根拠に基づいて最適化してください。

Selector 関数のメモ化

コンポーネント本体で selector をインライン作成すると、レンダリングのたびに新しい関数参照が作られ、メモ化が機能しなくなる可能性があります。selector はコンポーネントの外で定義するか、useCallback を使います。
// Outside component — stable reference
const selectName = s => s.user.name;

function Profile() {
  const name = useAppSelector(selectName);
  return <p>{name}</p>;
}

派生 Selector

別の selector の中から selector を呼び出して、selector を組み合わせます。派生 selector は基底 selector から値を計算し、ビジネスロジックをコンポーネントの外に保ちます。
const selectFullName = s => s.user.firstName + ' ' + s.user.lastName;

理解度チェック

useContextSelector または useMemo とともに使う場合、selector 関数をコンポーネント本体の外で定義するべきなのはなぜでしょうか?

まとめ

selector はコンテキスト state の一部分を取り出し、関係のない部分が変化したときの再レンダリングを防ぎます。安定した参照を保つため、selector はコンポーネントの外で定義します。本番環境で selector に対応するには、use-context-selector または Zustand を使います。

次のレッスン

次のレッスンは **When Not to Use Context** です。Context よりも props の受け渡し、コンポジション、state manager のほうが適している場面を見分ける方法を学びます。

よくある質問

「Context Selectorパターン」レッスンは無料ですか?

はい。「Context Selectorパターン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。

「Context Selectorパターン」で何を学びますか?

Contextの一部が変化したときだけ再レンダーするシンプルなselector hookを実装します。 ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

React Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのReact Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「Context Selectorパターン」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このReact Academyレッスンでコードを書いて実行できますか?

はい。すべてのReact Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 再レンダーを抑えるためのContext分割
  2. useMemoによるContext値のメモ化
  3. Context Selectorパターン
  4. Contextを使わないケース
← React Academyに戻る