Apollo boost - __typename в запросе предотвращает новую мутацию - PullRequest
0 голосов
/ 18 октября 2018

У меня есть проблема в моем проекте метеор / реагировать / аполлон (с наддувом).Когда я запрашиваю данные с сервера, он добавляет __typename к каждому объекту и подобъекту в моем запросе, но в моем случае это создает серьезную проблему, поскольку я обычно повторно использую эти данные для отправки их в другую мутацию.Теперь другая мутация говорит мне, что есть ошибка, потому что поле __typename не определено в моей схеме graphql.

Я попытался исправить, добавив поле addTypename: false в мой клиент apollo, но это ничего не изменило(обратите внимание, что я использую Apollo Boost, возможно, поэтому он не работает):

const client = new ApolloClient({
    uri: Meteor.absoluteUrl('graphql'),
    addTypename: false,
    request: operation =>
        operation.setContext(() => ({
            headers: {
                authorization: Accounts._storedLoginToken()
            }
        }))
})

Также кажется, что даже если он работает, он не очень оптимизирован.Мне кажется очень проблематичным, что в результаты запроса добавляется поле, и я удивлен, что не нашел какого-либо четкого решения в Интернете.Некоторое предлагаемое решение, где:

  • фильтр вручную на стороне клиента
  • добавление промежуточного программного обеспечения в apollo
  • добавление поля __typename ко всем моим схемам ...

но ни один из них, похоже, не подходит к «простоте», которую Аполлон должен принести для запросов.Я надеюсь, что есть более простое, более логичное решение, но пока не смог найти ни одного.

Ответы [ 2 ]

0 голосов
/ 16 февраля 2019

С здесь .«__typename» можно удалить с помощью следующей вспомогательной функции

const cleanedObject = omitDeep(myObject, "__typename")

const omitDeep = (obj, key) => {
    const keys = Object.keys(obj);
    const newObj = {};
    keys.forEach((i) => {
      if (i !== key) {
        const val = obj[i];
        if (val instanceof Date) newObj[i] = val;
        else if (Array.isArray(val)) newObj[i] = omitDeepArrayWalk(val, key);
        else if (typeof val === 'object' && val !== null) newObj[i] = omitDeep(val, key);
        else newObj[i] = val;
      }
    });
    return newObj;
  };

const omitDeepArrayWalk = (arr, key) => {
  return arr.map((val) => {
    if (Array.isArray(val)) return omitDeepArrayWalk(val, key)
    else if (typeof val === 'object') return omitDeep(val, key)
    return val
  })
}
0 голосов
/ 18 октября 2018

Даже если вы используете apollo-client, а не apollo-boost, вы не должны устанавливать addTypename в false, если у вас нет веских причин для этого.Поле __typename используется InMemoryCache для нормализации результатов запроса, поэтому его пропуск, вероятно, приведет к непредвиденному поведению при кэшировании.

К сожалению, для этой проблемы нет «серебряной пули».Запрос запроса и затем использование данных этого запроса в качестве переменной для другого запроса может быть истолковано как злоупотребление API.Type, возвращаемый запросом, и Input Type, используемые в качестве аргумента, - это совершенно разные вещи, даже если в качестве объектов Javascript они совместно используют одно или несколько полей.Точно так же, как вы не можете использовать типы и типы ввода взаимозаменяемо в схеме, не следует ожидать, что они могут использоваться взаимозаменяемо на стороне клиента.

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

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

В конце концов, выполнение подобных манипуляций, будем надеяться, будетисключение, а не правило.Я хотел бы создать некоторую вспомогательную функцию, чтобы «дезинфицировать» ваш ввод и двигаться дальше.

function stripTypenames (value) {
    if (Array.isArray(value)) {
        return value.map(stripTypenames)
    } else if (value !== null && typeof(value) === "object") {
      const newObject = {}
      for (const property in value) {
          if (property !== '__typename') {
            newObject[property] = stripTypenames(value[property])
          }
      }
      return newObject
    } else {
      return value
    }
}
...