Как использовать запросы детализации в apollo graphql reactjs?

#reactjs #graphql #apollo

#reactjs #graphql #apollo

Вопрос:

Предположим, data — это данные из родительского запроса.

Дочерний реагирующий компонент:

 const ShowDetails = ({data}) => {
   const { loading, error, data_details } = useQuery(someQueryAsksAdditionalFileldsForEntryAlreadyPresentInCache);
}
  

someQueryAsksAdditionalFileldsForEntryAlreadyPresentInCache — запрашивает дополнительные поля, которые отсутствуют в data .

Когда (!loading amp;amp; !error) data_details будут запрошены поля.

Проблема: data_details будут иметь только запрошенные поля.

Вопрос: Есть ли способ использовать родительские данные с объединенными полями дополнительного запроса в ShowDetails и игнорировать data_details ?

В Chrome с помощью Apollo devtools я вижу, что в apollo-cache есть одна запись из merged data и data_details .

Я не хочу повторно извлекать все существующие записи в data .

Пример:

Запрос родительского компонента:

 const bookQuery = gql`
  query ($bookId: ID!) {
    book(id: $bookId) {
      id
      author
    }
  }
`
  

Запрос деталей:

 const bookEditionsQuery = gql`
  query ($bookId: ID!) {
    book(id: $bookId) {
      id
      editions {
        publisher
        year
      }
    }
  }
`
  
 const bookReviewQuery = gql`
  query ($bookId: ID!) {
    book(id: $bookId) {
      id
      review {
        user
        score
        date
      }
    }
  }
`
  

Все эти запросы будут заполнять одно и то же поле в Apollo cache: book with id .

Чего необходимо достичь: в компоненте react BookDetails :

иметь 1 объект с:

data.author
data.editions[0].year
data.review[0].user

Логически — это одна запись в кэше.

Спасибо за вашу помощь.

Комментарии:

1. нет необходимости в слиянии / передаче от родительского элемента… просто запрашивайте ВСЕ обязательные поля, используя политику только для кэша

2. Это соответствует этому @xadm: цитата по ссылке: Существуют разные политики выборки, которые вы можете использовать при запуске запросов graphql . когда для политики выборки установлено значение fetchPolicy: ‘только для кэша’ . Вы говорите, что эта политика выборки позволяет избежать каких-либо сетевых запросов. Если запрашиваемые данные недоступны в кэше, это выдаст ошибку.

3. Я думаю, cache-first также не поможет: если в кэше отсутствуют некоторые запрошенные вами данные, Apollo отправит сетевой запрос к вашему API в соответствии с запросом — это означает повторную выборку всех полей.

4. если не все уже в кэше, вы можете объединить, используя OnCompleted

5. Объединить два данных непросто. Два запроса parent details могут иметь определенный набор полей. Например, у родительского элемента есть: ‘{ книга { автор }}’ details_query ‘{книга {издания { год}}}’ . Объединение двух объектов с одним и тем же набором ключей — это непросто.

Ответ №1:

Почти нечего сохранять, используя уже извлеченные [и переданные из родительских] данных… Только author … все обзоры и редакции должны быть извлечены, кэш вообще не используется.

… выборка review и editions с помощью book преобразователя помогает apollo cache сохранять связь, но также требует, чтобы API использовал дополнительный (‘book’) преобразователь [уровня], хотя это не требуется… распознаватели обзоров и выпусков должны вызываться напрямую с идентификатором книги… и т. д. может использоваться отдельным <Review /> подкомпонентом… или review и editions вызывается в рамках одного запроса с использованием одного и того же параметра id.

Просто используйте data и dataDetails отдельно в компоненте — избегайте усложнений кода, сохраняйте его простым для чтения:

 const ShowDetails = ({data}) => {
   const { loading, error, data:dataDetails } = useQuery(someQueryAsksAdditionalFileldsForEntryAlreadyPresentInCache);
}
if(loading) return "loading...";
return (
  <div>
    <div>author: {data.author}</div>
    {dataDetails.review.map(...
  

… если вы действительно хотите объединить данные

 const ShowDetails = ({data}) => {
   const [bookData, setBookData] = useState(null);
   const { loading, error, data:dataDetails } = useQuery(someQueryAsksAdditionalFileldsForEntryAlreadyPresentInCache, {
    onCompleted: (newData) => {
        setBookData( {...data, ...newData } );
      }
    });
    if(bookData) return ...
      // {bookData.author}
      // bookData.review.map(...