web-dev-qa-db-ja.com

Apollo / GraphQl-タイプは入力タイプである必要があります

私が学習プロセスにあり、ApolloとgraphQLを私のプロジェクトの1つに統合しているときに、皆さんに連絡します。これまでのところ問題はありませんが、現在、いくつかの変更を試みており、入力タイプとクエリタイプで苦労しています。本来よりもずっと複雑な気がするので、どうやって自分の状況を管理すべきかアドバイスを求めています。私がオンラインで見つけた例は常に非常に基本的なスキーマですが、私のスキーマは非常に大きく、次のように見えるため、現実は常により複雑です(一部だけをコピーします)。

type Calculation {
    _id: String!
    userId: String!
    data: CalculationData
    lastUpdated: Int
    name: String
}

type CalculationData {
    Loads: [Load]
    validated: Boolean
    x: Float
    y: Float
    z: Float
    Inputs: [Input]
    metric: Boolean

}

次に、入力と負荷が定義されます。

このために、「計算」を保存するためのミューテーションが必要なので、同じファイルに次のようになります。

type Mutation {
    saveCalculation(data: CalculationData!, name: String!): Calculation
}

私のリゾルバは次のとおりです。

export default resolvers = {
    Mutation: {
        saveCalculation(obj, args, context) {
            if(context.user && context.user._id){
                const calculationId = Calculations.insert({
                    userId: context.user._id,
                    data: args.data,
                    name: args.name
                })
                return Calculations.findOne({ _id: calculationId})
            }
            throw new Error('Need an account to save a calculation')
        }
    }
}

次に、私の突然変異は次のとおりです。'graphql-tag 'からgqlをインポートします。

export const SAVE_CALCULATION = gql`
    mutation saveCalculation($data: CalculationData!, $name: String!){
        saveCalculation(data: $data, name: $name){
            _id
        }
    }
`

最後に、Mutationコンポーネントを使用してデータを保存しようとしています。

<Mutation mutation={SAVE_CALCULATION}>
    {(saveCalculation, { data }) => (
        <div onClick={() => saveCalculation({ variables : { data: this.state, name:'name calcul' }})}>SAVE</div>
    }}
</Mutation>

今、私は次のエラーを受け取ります:

[GraphQLエラー]:メッセージ:Mutation.saveCalculation(data :)のタイプは入力タイプである必要がありますが、取得:CalculationData!。、場所:未定義、パス:未定義

私の調査と他のいくつかのSO投稿から、クエリタイプに加えて入力タイプを定義する必要があることがわかりましたが、入力タイプはスカラータイプのみを平均できますが、私のスキーマは他のスキーマに依存しています(そして最後の入力タイプがスカラータイプしかない場合など、他の入力タイプに応じて入力タイプを作成できますか?冗長性が高いように見えるため、少し迷っています。ベストプラクティスに関するガイダンスをいただければ幸いです。 。私は確信していますApollo/graphql私のプロジェクトでは、時間の経過とともに非常に良い助けをもたらすことができますが、スキーマが少し複雑な場合、実装するよりも複雑であることを認めなければなりません。オンラインの例通常、文字列とブール値に固執します。

7
Ivo

spec から:

フィールドは、動作を構成するための引数を受け入れる場合があります。これらの入力は多くの場合スカラーまたは列挙型ですが、より複雑な値を表す必要がある場合もあります。

GraphQL入力オブジェクトは、入力フィールドのセットを定義します。入力フィールドは、スカラー、列挙型、またはその他の入力オブジェクトのいずれかです。これにより、引数は任意の複雑な構造体を受け入れることができます。

つまり、通常のGraphQLObjectTypesをGraphQLInputObjectTypeフィールドのタイプとして使用することはできません。別のGraphQLInputObjectTypeを使用する必要があります。

SDLを使用してスキーマを書き出す場合、特に同じフィールドがある場合は、Load型とLoadInput入力を作成する必要があるのは冗長に思えるかもしれません。ただし、内部では、定義するタイプと入力は、それぞれ異なるプロパティとメソッドを持つ非常に異なるクラスのオブジェクトに変換されます。 GraphQLObjectTypeには存在しないGraphQLInputObjectTypeに固有の機能(引数の受け入れなど)があり、その逆もあります。

別のものの代わりに使用しようとすることは、丸い穴に四角いペグを入れようとするようなものです。 「なぜ円が必要なのかわかりません。正方形があります。両方とも直径があります。なぜ両方が必要なのですか?」

それ以外に、タイプと入力を分離しておくことには実用的な理由があります。これは、多くのシナリオで、入力では公開しないタイプのフィールドを多数公開するためです。

たとえば、タイプに、実際には基になるデータの組み合わせである派生フィールドが含まれている場合があります。または、他のデータとの関係へのフィールドが含まれる場合もあります(friendsUserフィールドなど)。どちらの場合も、これらのフィールドを、一部のフィールドの引数として送信されるデータの一部にすることは意味がありません。同様に、対応するタイプに公開したくない入力フィールドがある場合があります(passwordフィールドが思い浮かびます)。

6
Daniel Rearden

はい、できます:

入力オブジェクトタイプのフィールド自体は入力オブジェクトタイプを参照できますが、スキーマで入力タイプと出力タイプを混在させることはできません。入力オブジェクトタイプも、フィールドに引数を持つことはできません。

入力タイプは、通常のタイプに加えて定義されることを意図しています。通常、これらにはいくつかの違いがあります。たとえば、入力にはidまたはcreatedAtフィールドがありません。

1
Loren