apollographql / react-apollo

:recycle: React integration for Apollo Client
https://www.apollographql.com/docs/react/
MIT License
6.85k stars 790 forks source link

Optimistic data not available via `cache.readQuery` inside a local resolver #3639

Open lensbart opened 4 years ago

lensbart commented 4 years ago

Hello homies,

When executing a remote mutation with an optimistic response, the optimistic data is not available via cache.readQuery in the resolver of another local mutation that’s run in quick succession afterwards.

The problem occurs reproducibly in the following sequence of steps:

  1. Run a mutation which has an optimistic response
// Inside component 1
const [remoteMutation] = useMutation(REMOTE_MUTATION, {
  optimisticResponse: { /* ... */ },
  update: (cache, { data }) => {
    // ...
    const oldData = cache.readQuery({ query: QUERY, variables })
    cache.writeQuery({ data: fn(oldData), query: QUERY, variables })
    // (*) (cf. below)
  }
})
  1. Have a component that rerenders due to the optimistic response, and have it execute a local query via useEffect or useLayoutEffect
// Inside component 2
const [niceLocalMutation] = useMutation(NICE_LOCAL_MUTATION)
useLayoutEffect(() => {
  niceLocalMutation({
    variables: { input: { /* optimisticResponse from REMOTE_MUTATION used here */ } }
  })
})
  1. Observe that the optimistic response is not available in the local mutation resolver:
// niceLocalMutation resolver
export default (
  _,
  { input: { /* optimistic response from REMOTE_MUTATION above */ } },
  { cache }
) => {
  const data = cache.readQuery({ query: QUERY, variables })
  // here, `data` doesn’t contain the optimistic response from `REMOTE_MUTATION`
}

By contrast, the actual server response (2nd time the update function of the remote mutation remoteMutation is run) is available in the local mutation resolver.

I checked to confirm that the store got updated correctly, by checking the value of cache.readQuery immediately after writing to the store in the update function of the remote mutation (at the position of the comment // (*) above). Here, I could see the optimistic response data in the Apollo store.

I ensured that none of my mutations are mutating variables (see https://github.com/apollographql/react-apollo/issues/3290 for the description of an identical problem). To be extra sure, I wrapped the data passed to cache.writeQuery in clone() from Ramda, a utility library, to the same effect.

 System:
    OS: macOS 10.15
  Binaries:
    Node: 12.10.0 - /usr/local/bin/node
    Yarn: 1.19.1 - ~/Documents/GitHub.nosync/codebase/node_modules/.bin/yarn
    npm: 6.10.3 - /usr/local/bin/npm
  Browsers:
    Chrome: 77.0.3865.120
    Firefox: 69.0.3
    Safari: 13.0.2
  npmPackages:
    @apollo/react-hooks: ^3.0.0 => 3.1.3 
    @apollo/react-ssr: ^3.0.0 => 3.1.3 
    @apollo/react-testing: ^3.0.0 => 3.1.3 
    apollo: ^2.3.1 => 2.21.0 
    apollo-cache-inmemory: ^1.0.0 => 1.6.3 
    apollo-client: ^2.2.5 => 2.6.4 
    apollo-link: ^1.2.3 => 1.2.13 
    apollo-link-error: ^1.0.5 => 1.1.12 
    apollo-link-http: ^1.3.2 => 1.5.16 
    apollo-link-schema: ^1.2.2 => 1.2.4 
    apollo-link-ws: ^1.0.18 => 1.0.19 
    apollo-server: ^2.0.5 => 2.9.7 
    apollo-server-express: ^2.0.3 => 2.9.7 
    apollo-utilities: ^1.3.2 => 1.3.2 

Thanks in advance for your insight and help!

damonvjanis commented 4 years ago

I'm seeing the same thing in a small project I'm doing on the side. I can give more details and steps to reproduce as well if it's helpful, but I just wanted to 1+ this.

lednhatkhanh commented 4 years ago

+1 this, can also be reproduced in my project.