0
votes

Suppose data - is data from a parent query.

Child react-component:

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

someQueryAsksAdditionalFileldsForEntryAlreadyPresentInCache -- asks for additional fields that are missing in data.

When (!loading && !error) data_details will have requested fields.

Issue: data_details will have only requested fields.

Question: Is there a way to use parent data with merged-additional-requested fields in ShowDetails and ignore data_details?

In Chrome with help of Apollo devtools I see that apollo-cache has one entry from merged data and data_details.

I do not want to re-fetch all existed entries in data.

Example:

Parent component query:

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

Details query:

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
      }
    }
  }
`

All this queries will populate the same bucket in Apollo cache: book with id.

What is necessary to achieve: in react component BookDetails:

have 1 object with:

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

Logically - this is one entry in cache.

Thank you for your help.

1
no need to merge / passing from parent ... just query for ALL required fields using cache-only policy - xadm
This does align with this @xadm: quote from the link: There are different fetch-policy which you can use when firing the graphql queries . when fetch policy is set to fetchPolicy: 'cache-only' . You are saying that , This fetch policy avoids making any network requests.If the data you are querying is not available in the cache, it will throw an error. - user14276800
I think cache-first also will not help : If the cache is missing some of the data you asked for, Apollo will make a network request to your API according to query - this means re-fetch all fields. - user14276800
if not all already in cache then you can merge using onCompleted - xadm
Merging two data is not easy. The two queries parent + details can have specific set of fields. Example parent have: '{ book { author }}' details_query '{book {editions { year}}}' . Merging two object with the same set of keys something not easy. - user14276800

1 Answers

0
votes

Almost nothing to save by using already fetched [and passed from parent] data ... only author ... all review and edition must be fetched, no cache usage at all.

... fetching review and editions by book resolver helps apollo cache to keep relation but also requires API to use additional ('book') resolver [level] while it is not required ... review and editions resolvers should be callable directly with book id ... and f.e. can be used by separate <Review /> sub component ... or review and editions called within one request using the same id parameter.

Just use data and dataDetails separately in component - avoid code complications, keep it simply readable:

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

... if you really want to join data

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