#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(...