Реагирование Apollo на обновление клиентского кэша после мутации - PullRequest
0 голосов
/ 06 октября 2019

Я пытаюсь обновить мою chache после успешного выполнения мутации. Вот мой запрос и мутация:

export const Dojo_QUERY = gql`
query Dojo($id: Int!){
  dojo(id: $id){
    id,
    name,
    logoUrl,
    location {
     id,
     city,
     country
    },
    members{
      id
    },
    disziplines{
      id,
      name
    }
  } 
}`;


export const addDiszipline_MUTATION = gql`
mutation createDisziplin($input:DisziplineInput!,$dojoId:Int!){
  createDisziplin(input:$input,dojoId:$dojoId){
    disziplin{
     name,
     id
    }
  }
}`;

и мой вызов мутации:

const [createDisziplin] = useMutation(Constants.addDiszipline_MUTATION,
    {
      update(cache, { data: { createDisziplin } }) {
        console.log(cache)
        const { disziplines } = cache.readQuery({ query: Constants.Dojo_QUERY,variables: {id}});
        console.log(disziplines)
        cache.writeQuery({
        ...some update logic (craches in line above)
        });
      }
    }
    );

когда я выполняю эту мутацию, я получаю ошибку

Invariant Violation: "Can't find field dojo({"id":1}) on object {
  "dojo({\"id\":\"1\"})": {
    "type": "id",
    "generated": false,
    "id": "DojoType:1",
    "typename": "DojoType"
  }
}."

В моемклиентский кеш, который я вижу

data{data{DojoType {...WITH ALL DATA INSIDE APPART FROM THE NEW DISZIPLINE}}

и

data{data{DisziplineType {THE NEW OBJECT}}

Кажется, что вокруг кеша клиентов в Интернете много путаницы. Каким-то образом ни одно из предложенных решений не помогло или не имело никакого смысла для меня. Любая помощь будет принята с благодарностью.

РЕДАКТИРОВАТЬ 1: Может быть, это может помочь?

ROOT_QUERY: {…}
"dojo({\"id\":\"1\"})": {…}​​​​​
generated: false​​​​​
id: "DojoType:1"​​​​​
type: "id"​​​​​
typename: "DojoType"​​​​​
<prototype>: Object { … }​​​​
<prototype>: Object { … }

Редактировать 2

Я принял совет Herku и начал использовать фрагмент. однако это все еще, кажется, не совсем работает.

Мой обновленный код:

 const [createDisziplin] = useMutation(Constants.addDiszipline_MUTATION,
    {
      update(cache, { data: { createDisziplin } }) {
        console.log(cache)
        const { dojo } = cache.readFragment(
          { fragment: Constants.Diszilines_FRAGMENT,
            id:"DojoType:"+id.toString()});
        console.log(dojo)
      }
    }
    );

с

export const Diszilines_FRAGMENT=gql`
  fragment currentDojo on Dojo{
    id,
    name,
    disziplines{
      id,
      name
    }
  }
`;

однако результат от console.log(dojo) все еще не определен. Любой совет?

1 Ответ

0 голосов
/ 07 октября 2019

Так что я думаю, что ваша настоящая ошибка в том, что вы должны указать идентификатор в виде строки: variables: {id: id.toString()}. Вы можете видеть, что эти две строки различны:

dojo({\"id\":1})
dojo({\"id\":\"1\"})

Но я настоятельно рекомендую использовать readFragment вместо readQuery и обновить додзё с указанным идентификатором. Это должно обновить и запрос, и все остальные случаи додзё во всех ваших запросах. Вы можете найти документацию по readFragment здесь .

Еще один прием - просто вернуть целое додзё в ответ на мутацию. Я бы сказал, что люди должны меньше бояться этого и не делать слишком много обновлений кэша, потому что обновления кэша являются неявным поведением вашего API, которого нет в вашей системе типов. То, что новый disziplin можно найти в поле disziplins, теперь закодировано в вашем интерфейсе. Представьте, что вы хотите добавить еще один шаг, когда новые дисциплины должны быть одобрены прежде, чем они попадут туда. Если мутация возвращает целое додзё, простое изменение бэкэнда выполнит эту работу, и ваши клиенты не должны знать об этом поведении.

...