Apollo / GraphQl - тип должен быть типом ввода - PullRequest
0 голосов
/ 10 октября 2018

Обращаюсь ко всем вам в процессе обучения и интеграции Apollo и graphQL в один из моих проектов.Пока все идет хорошо, но сейчас я пытаюсь получить некоторые мутации и борюсь с типом ввода и типом запроса.Я чувствую, что все гораздо сложнее, чем должно быть, и поэтому я ищу совет о том, как мне справиться с ситуацией.Примеры, которые я нашел в Интернете, всегда содержат очень простые схемы, но реальность всегда более сложна, так как моя схема довольно большая и выглядит следующим образом (я скопирую только часть):

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')
        }
    }
}

Тогда моя мутация следующая: import gql из 'graphql-tag';

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 со временем может оказать мне довольно хорошую помощь в моем проекте, но я должен признать, что это сложнее, чем я думал, чтобы реализовать его, когда схемы немного сложны.В онлайн-примерах обычно используются строки и логические значения.

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Из spec :

Поля могут принимать аргументы для настройки своего поведения.Эти входные данные часто являются скалярами или перечислениями, но иногда они должны представлять более сложные значения.

Объект ввода GraphQL определяет набор полей ввода;Поля ввода являются скалярами, перечислениями или другими объектами ввода.Это позволяет аргументам принимать произвольно сложные структуры.

Другими словами, вы не можете использовать обычные GraphQLObjectType s в качестве типа для поля GraphQLInputObjectType - вы должны использовать другое GraphQLInputObjectType.

Когда вы записываете свою схему с использованием SDL, может показаться излишним создание типа Load и ввода LoadInput, особенно если они имеют одинаковые поля.Однако под капотом определяемые вами типы и входные данные превращаются в совершенно разные классы объектов, каждый из которых имеет свои свойства и методы.Существует функция, специфичная для GraphQLObjectType (например, принятие аргументов), которой нет в GraphQLInputObjectType - и наоборот.

Попытка использовать вместо другого это все равно, что пытаться вставить квадратный колышек в круглое отверстие.«Я не знаю, зачем мне круг. У меня есть квадрат. У них обоих диаметр. Зачем мне оба?»

Помимо этого, есть веская практическая причина для сохранения типов и входных данных.отдельный.Это связано с тем, что во многих сценариях вы будете выставлять множество полей того типа, которые вы не будете открывать для ввода.

Например, ваш тип может включать производные поля, которые на самом деле являются комбинацией базовых данных.,Или это может быть поле для связи с другими данными (например, поле friends для User).В обоих случаях не имеет смысла делать эти поля частью данных, представляемых в качестве аргумента для какого-либо поля.Аналогично, у вас может быть какое-то поле ввода, которое вы бы не хотели показывать в его аналоге типа (на ум приходит поле password).

0 голосов
/ 10 октября 2018

Да, вы можете:

Поля типа входного объекта могут сами относиться к типам входного объекта, но вы не можете смешивать типы ввода и вывода в своей схеме.Типы входных объектов также не могут иметь аргументы в своих полях.

Типы ввода должны быть определены в дополнение к обычным типам.Обычно они будут иметь некоторые отличия, например, у input не будет идентификатора или поля createAt. * ​​1005 *

...