Update Apollo GraphQL cache without using refetchQ

2019-07-19 17:08发布

I have a React app accessing GraphQL server with the Apollo Client (version 1.x). There is a server schema that looks like this.

type Query {
  currentShop: Shop
}
type Shop {
  id: ID!
  name: String!
  products: [Product!]!
  ...etc
}

I do have dataIdFromObject defined like this.

const dataIdFromObject = o => {
  if (o.__typename != null && o.id != null) {
    return `${o.__typename}-${o.id}`
  }
  return null
}

Throughout the app, I am running queries asking for different fields of currentShop. At various points there are also mutations that are changing the currentShop and the mutation is always returning resulting Shop type. However, there is no relation to the currentShop so Apollo cannot know how to update root query cache pointer.

I've made fully working demo representing the issue with CodeSandbox. The backend is made with Apollo LaunchPad. Picking a different branch, waiting couple seconds (did not bother with optimizations) and it works.

The "magic" is happening in the ShopSelectButton component. If you comment out refetchQueries line, things get broken. The shop is correctly selected on the server (and you see it after reload), but client acts like a dead animal.

My problem is with refetchQueries as it makes code too tightly couple. I don't want to have a component in one part of the app to know about any other component and their needs. Also honestly, refetching means it goes around whole caching and it always reads from backend which is unnecessary in most cases.

I am wondering what are other approaches to this. Should the schema be built more stateless and keep the state in the frontend app instead?

1条回答
劳资没心,怎么记你
2楼-- · 2019-07-19 17:47

I think the mutation should work without refetching the queries. You just need to add all the required data from the related queries in the mutation result body.

Did you try to install the apollo client development tool extension for chrome? There you could easily see if the currentShop element in the different queries is related via the typename and id to a Shop type. If this is the case apollo should update after the mutation.

To get all required data for the mutation result to update correctly i suggest you add a fragments structure to your app. Meaning that all components which need data from the shop have a fragments field defining the requirements. The fragments are collected and added to the mutation body. Of course doing this you have the same coupling between the other components and the mutation.

Another option would be to add all possible data of the Shop type to the result of the mutation.

查看更多
登录 后发表回答