Apollo client v3 «Данные кэша могут быть потеряны при замене поля X объекта Y»

#reactjs #apollo-client #react-apollo #apollo-cache-inmemory

#reactjs #apollo-client #реагировать-apollo #apollo-cache-inmemory

Вопрос:

У меня есть два простых запроса:

 query GerMenuA {
  menus {
    menuA {
      items {
        label
      }
    }
  }
}

query GerMenuB {
  menus {
    menuB {
      items {
        label
      }
    }
  }
}
 

Но в консоли я вижу предупреждение:

 Cache data may be lost when replacing the menus field of a Query object.
existing: {"__typename":"Menu","menuA":[{...}]}
incoming: {"__typename":"Menu","menuB":[{...}]}
 

Есть ли способ просто не объединять их и удалить предупреждение? Потому что, если указать в typePolicies

 Menu: { merge: true }
or
Menu: { merge: false }
 

это не то, что я хочу, потому что это разные данные, и эти две очереди не нужно каким-либо образом объединять. Кроме того, у меня нет id поля и keyFields оно не будет работать в этом случае, потому что метки могут быть одинаковыми для обоих меню

Ответ №1:

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

 type Query {
  menus: Menus
}
type Menus {
  menuA: Menu
  menuB: Menu
}
 

В предупреждении, по сути, говорится, что без какого-либо keyArgs Apollo Cache невозможно нормализовать menus запрос. Имейте в виду, с их точки зрения — у вас один menus корневой запрос. (т. Е. GerMenuA GerMenuB Запросы на стороне клиента, а не корневые запросы).

(Примечание — поскольку у вас нет id полей, см. раздел Отключение нормализации.)

Вариант 1: разделите ваши запросы

 type Query {
  menuA: Menu
  menuB: Menu
}
 

Кэш Apollo теперь будет хранить menuA и menuB как отдельные запросы. Если вы хотите быть в безопасности, вы можете установить свои политики типов:

 const createCache = () => new InMemoryCache({
  typePolicies: {
    Menu: {
      keyFields: false
    },
    Query: {
      fields: {
        menuA: {
          keyArgs: false
        },
        menuB: {
          keyArgs: false
        }
      }
    }
  },
});
 

keyFields: false сообщает AC о сохранении Menu в соответствии с его родительским запросом. keyArgs: false говорит, что оба menuA и menuB являются одноэлементными запросами. Политика кэша по умолчанию будет merge: false такой, чтобы существующие данные были заменены входящими.

Вариант 2: определить параметр запроса

В этом случае вы добавляете name параметр в свой menus запрос:

 type Query {
  menus(name: String): Menu
}
 

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

Кэш Apollo теперь будет хранить menus:{name:menuA} и menus:{name:menuB} как отдельные объекты кэша. Опять же, если вы хотите быть в безопасности, вы можете установить свои политики типов:

 const createCache = () => new InMemoryCache({
  typePolicies: {
    Menu: {
      keyFields: false
    }
  },
});
 

Опять же, политика кэша по умолчанию будет merge: false такой, чтобы существующие данные были заменены входящими.

Вариант 3: определение политики слияния

Мы рассмотрели, почему существующая схема сбивает с толку Apollo Cache. Но если вы действительно настроены на это, осталось определить политику слияния:

 const createCache = () => new InMemoryCache({
  typePolicies: {
    Menu: {
      keyFields: false
    },
    Menus: {
      keyFields: false,
      merge: true
    },
    Query: {
      fields: {
        menus: {
          keyArgs: false,
          merge: true
        }
      }
    }
  },
});
 

merge: true сообщает Apollo Cache объединить результаты GerMenuA и GerMenuB в один Menus объект кэша с обоими menuA menuB свойствами и . Без этого при каждом запуске запроса вы бы уничтожали результаты предыдущего запроса.