简体   繁体   中英

Apollo client returns no result on cache-only even if cache does contain data

With the two following schema:

type Cart {
  id:ID!
  ...
  createdAt:DateTime
  updatedAt:DateTime

  items:[CartItem!]
}

type CartItem {
   id:ID!
   cartId:ID!
   name:String!
   price:Float
}

type Query {
   userCart(id:ID!):Cart
   cartItem(id:ID!):CartItem
}

and the following queries:

const CART_QUERY = gql`query GetCart {
   userCart {
      id
      createdAt
      updatedAt

      items {
        id
        name
        price
      }
   }
}`;

const CART_ITEM_QUERY = gql`query CartItem($id:ID!) {
  cartItem(id:$id) {
    id
    name
    price
  }
}`;

If one component is defined as

function CartComponent() {
   const { loading, error, data } = useQuery(CART_QUERY);

   return ( /* content here */ );
};

which populates the cache with, for example:

Cart:123
CartItem:5463
CartItem:5472

and another component, child of CartComponent , is defined as

function CartItemEditComponent({ itemId }) {
   const [ fetch, { loading, error, data } ] = useLazyQuery(CART_ITEM_QUERY);

   useEffect(() => {
     // itemId = 5463
     fetch({ id:itemId }, { fetchPolicy:'cache-only' });
   }, [itemId, fetch]);

   console.log( data, error );  // <--- always : undefined undefined

   return ( /* content here */ );
};

If I remove the option fetchPolicy:'cache-only' then a server request is made and data does contain the CartItem ; no change to the cache , However, with the cache-only fetch policy, the component is still rendered, but data is empty with no error.

Why is data inside CartItemEditComponent empty with fetchPolicy:'cache-only' ?

If the query is the issue, then what should be the value of CART_ITEM_QUERY ?


Update

The way I make it work, right now, is by doing this:

function CartComponent() {
   const { loading, error, data, client } = useQuery(CART_QUERY);

   useEffect(() => {
      const items = data?.userCart?.items ?? [];

      for (const item of items) {
         client.writeQuery({
            query: CART_ITEM_QUERY,
            data: { cartItem: item },
            variables: { id: item.id }
         });
      }
   }, [data, client]);

   return ( /* content here */ );
};

The cache isn't modified, but the CartItemEditComponent suddenly has a result.

Based on my comment above something like this should work:

function CartItemEditComponent({ itemId }) {
   const [ fetch, { loading, error, data } ] = useLazyQuery(CART_ITEM_QUERY);

   useEffect(() => {
     // itemId = 5463
     fetch({ id:itemId }, { fetchPolicy:'cache-only' });
   }, [itemId, fetch]);

   if (error) {
      console.log( error );
   }

   if (!data && loading) {
      <p>loading</p>
   }
   if (!loading && data) {
      return ( /* content here */ );
   }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM