Ошибка: Ошибка сети: Ошибка записи результата для хранения запроса (Apollo Client)

Я использую Apollo Client, чтобы сделать приложение для запроса моего сервера с помощью Graphql. У меня есть сервер python, на котором я выполняю свои запросы graphql, которые извлекают данные из базы данных и затем возвращают их клиенту.

Я создал пользовательский NetworkInterface для клиента, который помогает мне сделать индивидуальный запрос сервера (по умолчанию ApolloClient делает POST-вызов указанному URL-адресу). Сетевой интерфейс должен иметь метод query(), в котором мы возвращаем обещание для результата формы Promise<ExecutionResult>.

Я могу сделать вызов сервера и получить запрошенные данные, но все равно получить следующую ошибку.

Error: Network error: Error writing result to store for query 
{
   query something{
      row{
         data
      }
   }
}
Cannot read property 'row' of undefined
    at new ApolloError (ApolloError.js:32)
    at ObservableQuery.currentResult (ObservableQuery.js:76)
    at GraphQL.dataForChild (react-apollo.browser.umd.js:410)
    at GraphQL.render (react-apollo.browser.umd.js:448)
    at ReactCompositeComponent.js:796
    at measureLifeCyclePerf (ReactCompositeComponent.js:75)
    at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (ReactCompositeComponent.js:795)
    at ReactCompositeComponentWrapper._renderValidatedComponent (ReactCompositeComponent.js:822)
    at ReactCompositeComponentWrapper._updateRenderedComponent (ReactCompositeComponent.js:746)
    at ReactCompositeComponentWrapper._performComponentUpdate (ReactCompositeComponent.js:724)
    at ReactCompositeComponentWrapper.updateComponent (ReactCompositeComponent.js:645)
    at ReactCompositeComponentWrapper.performUpdateIfNecessary (ReactCompositeComponent.js:561)
    at Object.performUpdateIfNecessary (ReactReconciler.js:157)
    at runBatchedUpdates (ReactUpdates.js:150)
    at ReactReconcileTransaction.perform (Transaction.js:140)
    at ReactUpdatesFlushTransaction.perform (Transaction.js:140)
    at ReactUpdatesFlushTransaction.perform (ReactUpdates.js:89)
    at Object.flushBatchedUpdates (ReactUpdates.js:172)
    at ReactDefaultBatchingStrategyTransaction.closeAll (Transaction.js:206)
    at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:153)
    at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:62)
    at Object.enqueueUpdate (ReactUpdates.js:200)

Я хочу знать возможную причину ошибки и решения, если это возможно.

Ответ 1

У меня была похожая ошибка. Я решил, добавив идентификатор к запросу. например, мой текущий запрос был

query  {
  service:me {
    productServices {
      id
      title
    }
  }
}

мой новый запрос был

query  {
  service:me {
    **id**
    productServices {
      id
      title
    }
  }
}

Ответ 2

нам нужно включить id, в противном случае это приведет к указанной ошибке.

{
   query something {
      id
      row {
         id
         data
      }
   }
}

Ответ 3

У меня была аналогичная проблема.

Возможно, ваше приложение пыталось написать (данные ответа сети) в хранилище с неправильным адресом магазина?

Решение для моей проблемы

Я обновлял хранилище после добавления player в team:

// Apollo option object for `mutation AddPlayer`
update: (store, response) => {
  const addr = { query: gql(QUERY_TEAM), variables: { _id } };
  const data = store.readQuery(addr);
  stored.teams.players.push(response.data.player));
  store.writeQuery({...addr, data});
}

Я начал получать аналогичную ошибку выше (я на Apollo 2.0.2)

После перекопа в хранилище я понял, что мой запрос QUERY_TEAM сделан с одной переменной meta по умолчанию null. Кажется, что "адрес" магазина использует * stringified addr для идентификации записи. Поэтому я изменил свой код выше, чтобы имитировать include: null:

// Apollo option object for `mutation AddPlayer`
update: (store, response) => {
  const addr = { query: gql(QUERY_TEAM), variables: { _id, meta: null } };
  const data = store.readQuery(addr);
  data.teams.players.push(response.data.player));
  store.writeQuery({...addr, data});
}

И это исправило мою проблему.

* По умолчанию undefined вместо null вероятно избежит этой неприятной ошибки (непроверенной)

Дополнительная информация

Моя проблема может быть только касательной, поэтому, если это не помогает, у меня есть два совета:

Сначала, добавьте эти 3 строки в node_modules/apollo-cache-inmemory/lib/writeToStore.js, чтобы предупредить вас, когда "запись" пуста. И затем исследуйте _a, чтобы понять, что происходит не так.

exports.writeResultToStore = writeResultToStore;
function writeSelectionSetToStore(_a) {

    var result = _a.result, dataId = _a.dataId, selectionSet = _a.selectionSet, context = _a.context;
    var variables = context.variables, store = context.store, fragmentMap = context.fragmentMap;

    +if (typeof result === 'undefined') {
    +    debugger;
    +}

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

Ответ 4

Я наконец-то узнал, что является причиной этой проблемы после нескольких месяцев борьбы с ней в различных частях нашего приложения. То, что помогло пролить некоторый свет на это, было переключение с apollo-cache-inmemory на apollo-cache-hermes.

Я экспериментировал с Гермесом, надеясь смягчить эту проблему, но, к сожалению, он не может обновить кэш так же, как apollo-cache-inmemory. Что любопытно, так это то, что в отличие от apollo-cache-inmemory, hermes показывает очень приятное сообщение. Это привело меня к открытию, что кеш действительно сталкивается с этой проблемой, когда пытается сохранить тип объекта, который уже находится в кеше с идентификатором и идентификатором, но в новом типе объекта его нет. Так что apollo-cache-inmemory должен работать нормально, если вы тщательно согласовывает запросы к своим полям. Если вы опустите поле id везде для определенного типа объекта, оно будет работать успешно. Если вы используете поле id везде, оно будет работать правильно. Как только вы смешиваете запросы с идентификатором и без него, то когда кеш взрывается с этим ужасным сообщением об ошибке.

Это не ошибка - она работает как задумано, она просто нигде не документирована - см. эту спецификацию spec. Я действительно хотел бы, чтобы Аполлон задокументировал это ограничение где-нибудь.