apollographql / apollo-client

:rocket:  A fully-featured, production ready caching GraphQL client for every UI framework and GraphQL server.
https://apollographql.com/client
MIT License
19.32k stars 2.65k forks source link

`fetchPolicy: 'network-only'` receives no broadcasts under certain conditions #10802

Open jsindos opened 1 year ago

jsindos commented 1 year ago

Issue Description

I have the following schema:

  type Query {
    products: [Product]
  }

  type Product {
    id: Int
    isLiked: Boolean
  }

  type Mutation {
    toggleProductIsLiked(id: Int, isLiked: Boolean): Product
  }

I am calling this schema as follows:

  const { data: { products } = { products: [] } } = useQuery(Products, {
    fetchPolicy: 'network-only',
    notifyOnNetworkStatusChange: 'notifyOnNetworkStatusChange'
  })

  const [toggleProductIsLikedMutation] = useMutation(ToggleProductIsLiked)

  const toggleIsLiked = async (id, isLiked) => {
    await toggleProductIsLikedMutation({
      variables: {
        id,
        isLiked
      },
      optimisticResponse: {
        toggleProductIsLiked: {
          __typename: 'Product',
          id,
          isLiked: !isLiked
        }
      }
    })
  }

The server is inverting the boolean value of isLiked:

  Mutation: {
    toggleProductIsLiked (root, args) {
      const { id, isLiked } = args
      return { id, isLiked: !isLiked }
    }
  }

useQuery(Products) is not getting the broadcasted result of toggleProductIsLikedMutation (isLiked flipping) when both of the following conditions are true:

  1. The fetchPolicy is set to network-only
  2. optimisticResponse is set

I am wondering if this behaviour is intended, and if there is any easy way to circumvent this behaviour without having to switch either of these things off?

Link to Reproduction

https://github.com/jsindos/NetworkOnlyReceivesNoBroadcasts

Reproduction Steps

No response

phryneas commented 1 year ago

Hi @jsindos,

thank you for reporting this. This is definitely not intended, and most likely a bug. We'll investigate this.

jerelmiller commented 2 months ago

Hey @jsindos 👋

Thanks for your patience on this issue! We've done some investigating and unfortunately it appears that the behavior you're seeing was the original intended behavior of a network-only fetch policy. Unfortunately it seems that not all of the library followed through on the original intention of the fetch policy, hence why you're seeing this "under certain conditions". I think this issue highlights the fact that we really need to focus on clarifying how a fetch policy affects the lifetime of a query.

After more discussion, we've determined that we don't think we have a great way to address this issue that wouldn't otherwise break existing behavior in the library, or at the very least, introduce inconsistency. Either way we go with this would be introducing a breaking change somewhere. We have no way of determining how many apps rely on the existing behavior as a feature of the library.

Unfortunately this means we'll need to leave this "broken" for now. We'd like to address fetch policies more broadly in a future major so we can really ensure their behavior is standard across all of the client and clarify the intention behind them. I'll leave this issue open for this reason.

For now, our recommendation is to use the nextFetchPolicy option with cache-first so that updates will rerender as you expect.