Apollo can't access queryVariables in update:

2019-07-22 06:44发布

问题:

I am trying to use update: to update a query after performing a mutation. The problem is that the query in the store has several different variables applied and I would like to update the query and return it with the same variables.

I found in the docs that updateQueries has an option to include queryVariables which are the last set of variables that the query was executed with.

I have not found anything that describes how to retrieve the queryVariables or something like it from inside of update.

Inside of update: I can use

lastQuery = Object.keys(store.data.ROOT_QUERY).slice(-1)[0]

which will return a result like "userRecipes({"first":20,"minTime":0,"maxTime":500,"filterType":"Explore","searchTerm":""})"

The hacky way that I am doing this now is to parse that string to pull out the variables so I can finally use readQuery like so:

      const lastQuery = Object.keys(store.data.ROOT_QUERY).slice(-1)[0] 
      const searchPosition = lastQuery.search("searchTerm")
      const searchTerm = lastQuery.slice((searchPosition + 13),-3)

      // also parsing the lastQuery string for filterType, minTime, maxTime

      const data = store.readQuery({ 
        query: QUERY_USER_RECIPES, 
        variables: { 
                filterType: filterType,
                searchTerm: searchTerm,
                minTime: minTime,
                maxTime: maxTime,
        }
      });

This can't be the best way to do this. Is there a simpler way to access variables inside of update?

It seems like there should be a way to read the existing query and variables that are in the store without passing variables with readQuery.

Thanks for taking a look at this issue!

Version

apollo-client@1.4.0 react-apollo@1.4.2

回答1:

For apollo 2, but should be the same in 1.x

In the docs, you see that you can also pass variables to readQuery.

Here is an example where a user can book an event clicking a BookEvent component, if the mutation succeeds, it is reflected automatically in the upper component EventDetail.

In the component that tiggers the mutation (BookEvent), I pass store and eventId to a function declared in the upper component (EventDetail) and passed through props of the child component:

const onClick = () => createEventTicketMutation({
  variables: { eventId: event.id },
  update: (store, { data: { createEventTicket } }) => {
    updateStoreAfterBooking(store, event.id)
  },
})

Here is the function that performs the cache update in the upper component:

const updateCacheAfterBooking = (store, eventId) => {
  const data = store.readQuery({
    query: EVENT_DETAIL_QUERY,
    variables: { id: eventId },
  })
  data.eventDetail.bookings += 1
  store.writeQuery({
    query: EVENT_DETAIL_QUERY, 
    variables: { id: eventId },
    data,
  })
}

It is passed like so <BookEvent updateStoreAfterBooking={updateCacheAfterBooking} ... />.

Don't forget to pass also the needed variables to writeQuery.