2

私はGraphQLとRelayに飛び込んでいます。これまでのところ、すべてが比較的スムーズで簡単に理解できました。と を使用する GraphQL スキーマがAccountsありTeamsます。両者の間にはまだ関係はありません。アカウントとチームの両方について、接続用に Relay 固有の GraphQL 調整をいくつか行いました。これら 2 つの接続のクエリの例を次に示します...

{
  viewer {
    teams {
      edges {
        node {
          id,
          name
        }
      }
    }
    accounts {
      edges {
        node {
          id,
          username
        }
      }
    }
  }
}

新しいアカウントを作成する GraphQL ミューテーションの準備ができました。これがそのGraphQL表現です...

type Mutation {
  newAccount(input: NewAccountInput!): NewAccountPayload
}

input NewAccountInput {
  username: String!
  password: String!
  clientMutationId: String!
}

type NewAccountPayload {
  account: Account
  clientMutationId: String!
}

type Account implements Node {
  id: ID!
  username: String!
  date_created: String!
}

現在、この GraphQL ミューテーションを使用するクライアント側の Relay ミューテーションを作成しようとしています。ただし、これを正しく行う方法については完全に混乱しています。私は例に従ってきましたが、思いついたものは何も正しく実行されていないようです。フラグメントの構成に関連するエラーが発生する傾向があります。

この GraphQL ミューテーションを使用する Relay ミューテーションを作成する場合、適切なミューテーター構成は何でしょうか? を使用する必要がありRANGE_ADDますか?

4

2 に答える 2

6

クライアント側のミューテーションには、次のようなものを使用できます。

export default class AddAccountMutation extends Relay.Mutation {
   static fragments = {
      viewer: () => Relay.QL`
         fragment on Viewer {
            id,
         }
       `,
   };

   getMutation() {
      return Relay.QL`mutation{addAccount}`;
   }

   getVariables() {
      return {
         newAccount: this.props.newAccount,
      };
   }

   getFatQuery() {
      return Relay.QL`
         fragment on AddAccountPayload {
            accountEdge,
            viewer {
               accounts,
            },
         }
       `;
    }

   getConfigs() {
      return [{
         type: 'RANGE_ADD',
         parentName: 'viewer',
         parentID: this.props.viewer.id,
         connectionName: 'accounts',
         edgeName: 'accountEdge',
         rangeBehaviors: {
            '': 'append',
         },
      }];
   }

   getOptimisticResponse() {
      return {
         accountEdge: {
            node: {
               userName: this.props.newAccount.userName,
            },
         },
         viewer: {
            id: this.props.viewer.id,
         },
      };
   }
}

次に、GraphQL スキーマで、新しく作成されたエッジとカーソルを返す必要があります。

var GraphQLAddAccountMutation = mutationWithClientMutationId({
   name: 'AddAccount',
   inputFields: {
      newAccount: { type: new GraphQLNonNull(NewAccountInput) } 
   },
   outputFields: {
      accountEdge: {
         type: GraphQLAccountEdge,
         resolve: async ({localAccountId}) => {
            var account = await getAccountById(localAccountId);
            var accounts = await getAccounts();
            return {
              cursor: cursorForObjectInConnection(accounts, account)
              node: account,
            };
         }
      },
      viewer: {
        type: GraphQLViewer,
        resolve: () => getViewer()
      },
   },
   mutateAndGetPayload: async ({ newAccount }) => {
      var localAccountId = await createAccount(newAccount);
      return {localAccountId};
   }
});

var {
   connectionType: AccountsConnection,
   edgeType: GraphQLAccountEdge,
} = connectionDefinitions({
   name: 'Account',
   nodeType: Account,
});

getAccounts()、getAccountById()、および createAccount メソッド呼び出しを、サーバー/バックエンドが使用するものに置き換える必要があります。

複数のサーバートリップを行わずにカーソルを計算するためのより良い方法があるかもしれませんが、リレーヘルパーcursorForObjectInConnectionはオブジェクトの詳細な比較を行わないことに注意してください。リストでは、カスタム比較を行う必要がある場合があります。

function getCursor(dataList, item) {
   for (const i of dataList) {
      if (i._id.toString() === item._id.toString()) {
         let cursor = cursorForObjectInConnection(dataList, i);
         return cursor;
      } 
   }
}

最後に、GraphQL ミューテーションを「addAccount」としてスキーマ ミューテーション フィールドに追加します。これは、クライアント側のミューテーションによって参照されます。

于 2015-12-31T00:49:34.317 に答える