2

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 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

8 Comments

Yea, I don't like tight coupling, especially if my app needs to be modular to that extent it doesn't know what modules there would be.
Also, I don't think that relation you are describing is there. The currentShop is pointing to a particular typename:id and suddenly this gets changed on the server only. Apollo has no way of knowing that. I tried using writeQuery to update this pointer which essentially works, but it still lacks all other fields for all those queries.
Anyway, I came to realization that stateless server is probably better approach. This is the result of that attempt. codesandbox.io/s/ly9j7w1l9
Yeah, really nicely done! Injecting the store which holds the shop id
@FredyC, please post your solution as an answer so that others may benefit.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.