首页 文章

Apollo / GraphQl - 类型必须是输入类型

提问于
浏览
3

当我在学习过程中以及将Apollo和graphQL集成到我的一个项目中时,所有人都会接触到你们 . 到目前为止它还可以,但现在我想尝试一些突变,我正在努力使用Input类型和Query类型 . 我觉得它比它应该更复杂,因此我正在寻找关于如何管理我的情况的建议 . 我在网上找到的例子总是有非常基本的模式,但现实总是比较复杂,因为我的模式非常大,看起来如下(我只复制一部分):

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! . ,Location:undefined,Path:undefined

从我的研究和其他一些SO帖子中,除了Query类型之外,我还应该定义输入类型,但输入类型只能是标量类型,但我的模式依赖于其他模式(这不是标量) . 当最后一个只有标量类型时,我可以根据其他输入类型等创建输入类型吗?我有点失落,因为它似乎有很多冗余 . 非常感谢对最佳实践的一些指导 . 我确信 Apollo/graphql 可以在我的项目中为我带来很好的帮助,但是我不得不承认,当Schemas有点复杂时,它比我想象的要复杂得多 . 在线示例通常坚持使用String和Boolean .

2 回答

  • 1

    来自spec

    字段可以接受参数来配置其行为 . 这些输入通常是标量或枚举,但它们有时需要表示更复杂的值 . GraphQL输入对象定义一组输入字段;输入字段是标量,枚举或其他输入对象 . 这允许参数接受任意复杂的结构 .

    换句话说,您不能使用常规 GraphQLObjectType 作为 GraphQLInputObjectType 字段的类型 - 您必须使用另一个 GraphQLInputObjectType .

    当您使用SDL编写模式时,必须创建 Load 类型和 LoadInput 输入似乎是多余的,特别是如果它们具有相同的字段 . 但是,在引擎盖下,您定义的类型和输入将变为非常不同的对象类,每个类具有不同的属性和方法 . 有一些特定于 GraphQLObjectType (如接受参数)的功能在 GraphQLInputObjectType 上不存在 - 反之亦然 .

    试图用来代替另一个有点像试图在圆孔中放一个方形钉 . “我不知道为什么我需要一个圆圈 . 我有一个正方形 . 它们都有一个直径 . 为什么我需要两个?”

    除此之外,将类型和输入分开是一个很好的实际原因 . 这是因为在很多情况下,您将在输入上不会暴露的类型上暴露大量字段 .

    例如,您的类型可能包含实际上是基础数据组合的派生字段 . 或者它可能包括与其他数据关系的字段(如 User 上的 friends 字段) . 在这两种情况下,它都不会作为某个字段的参数提交 . 同样,您可能有一些输入字段,您不希望在其对应的类型上公开(想到一个 password 字段) .

  • 0

    是的你可以:

    输入对象类型上的字段本身可以引用输入对象类型,但不能在模式中混合输入和输出类型 . 输入对象类型也不能在其字段上包含参数 .

    除了普通类型之外,还要定义输入类型 . 通常它们会有一些差异,例如输入不会有id或createdAt字段 .

相关问题