派生フィールド
Relayレゾルバーは、クライアントの状態をモデル化することに加えて、他のフィールドの純粋関数として定義されたフィールドを定義することもできます。これらのフィールドは派生フィールドと呼ばれ、サーバーまたはクライアントで定義されているかに関係なく、どの型でも定義できます。
グローバルに関連するデータの場合、レゾルバーはReact Hooksなどの代替ソリューションよりもいくつかの利点があります。
- グローバルメモ化 - Relayレゾルバーは、派生フィールドを自動的にメモ化します。フックとは異なり、このキャッシュはアプリケーション内のすべてのコンポーネントによって共有されるため、2つの兄弟コンポーネントが同じフィールドを読み取ると、計算は1回だけ実行されます。
- 効率的な更新 - 派生レゾルバーが再計算しても同じ値を導出する場合、Relayはフィールドを読み取るコンポーネントの再レンダリングを回避できます。
- コンポーザブル - 派生フィールドは他の派生フィールドと組み合わせることができるため、複雑だが明示的な計算グラフを構築できます。
- 検出可能 - グラフ内の値はGraphQLスキーマを介して検出できるため、再発明する代わりに発見されて再利用される可能性が高くなります。
- ドキュメント化 - GraphQLのフィールドドキュメントと構造化された非推奨モデルにより、フィールドの目的とその意図された使用方法を簡単に理解できます。
派生レゾルバーの定義
派生レゾルバーは、親モデル型から計算されるのではなく、GraphQLデータを読み取る点を除いて、他のレゾルバーと同じように見えます。派生レゾルバーは、「ルートフラグメント」を定義することでGraphQLデータを読み取ります。これは、フィールドの親型で定義されたGraphQLフラグメントです。
ルートフラグメントは、@rootFragment docblockタグとフラグメントの名前を使用して定義されます。これは、Relayにそのフラグメントのフラグメントキーをレゾルバー関数に渡すように指示します。その後、relay-runtimeからインポートされたreadFragmentを使用して、フラグメントデータを読み取ることができます。
- Docblock
import {readFragment} from 'relay-runtime';
/**
 * @RelayResolver User.fullName: String
 * @rootFragment UserFullNameFragment
 */
export function fullName(key: UserFullNameFragment$key): string {
  const user = readFragment(graphql`
    fragment UserFullNameFragment on User {
        firstName
        lastName
    }
  `, key);
  return `${user.firstName} ${user.lastName}`;
}
Relayは、フラグメントから読み取られたすべての値を追跡し、それらの値のいずれかが変更されたときにレゾルバーを自動的に再計算します。
構成
派生レゾルバーの強力な機能の1つは、他のRelayレゾルバーフィールドを読み取ることができることです。つまり、サーバーデータ、クライアントデータ、さらには他の派生レゾルバーを組み合わせた派生レゾルバーを定義できます。これにより、複雑だが明示的な計算グラフを構築できます。
/**
 * @RelayResolver CheckoutItem.isValid: Boolean
 * @rootFragment CheckoutItemFragment
 */
export function isValid(key): boolean {
  const item = readFragment(graphql`
    fragment CheckoutItemFragment on CheckoutItem {
      product {
        price
      }
      quantity
    }
  `, key);
  return item.product.price * item.quantity > 0;
}
/**
 * @RelayResolver ShoppingCart.canCheckout: Boolean
 * @rootFragment ShoppingCartFragment
 */
export function canCheckout(key): boolean {
  const cart = readFragment(graphql`
    fragment ShoppingCartFragment on ShoppingCart {
      items {
        isValid
      }
    }
  `, key);
  return cart.items.every(item => item.isValid);
}
@rootFragmentへの引数の渡
派生レゾルバーのルートフラグメント内のフィールドに引数が必要な場合は、@argumentsタグをdocblockタグに追加して渡すことができます。@argumentタグは、引数の名前と引数の型を取ります。引数の型は、有効なGraphQL入力型である必要があります。引数とレゾルバーの詳細については、フィールド引数を参照してください。