1
votes

I have got an Angular 7 app that accesses data from a GraphQL server.

I directly implemented the example from the docs: https://www.apollographql.com/docs/react/advanced/caching.html#automatic-updates

This is the service that get the post object and executes the upvote mutation.

export class PostService {

  constructor(private apollo: Apollo) { }

  public getPost() {
    return this.apollo.query({
      query: gql`query getPost($id: String!) {
        post(id: $id) {
          id
          score
        }
      }`,
      variables: { id: '123' }
    });
  }

  public upvote() {
    return this.apollo.mutate({
      mutation: gql`mutation upvote($id: String!) {
        upvotePost(id: $id) {
          id
          score
        }
      }`,
      variables: { id: '123' }
    });
  }
}

in my component.ts file

  public post = this.postService.getPost();
  public vote() {
    this.postService.upvote().subscribe(console.log);
  }

in my component.html

    <input type="text" [value]="(post | async).data.post.score" />
    <button class="button" (click)="vote()"></button>

The value in the box does not change.

If I add an additional button that calls this function

public updateView() {
  post = this.postService.getPost();
}

The gui will update without querying the server, so obviously from cache.

According to the spec this manual refresh step is not supposed to be necessary.

If the id field on both results matches up, then the score field everywhere in our UI will be updated automatically!

Versions of my packages:

  • apollo-angular: 1.5.0
  • apollo-angular-link-http: 1.4.0
  • apollo-angular-link-http-common: 1.4.0
  • apollo-cache: 1.1.25
  • apollo-cache-inmemory: 1.4.2
  • apollo-client: 2.4.12

What do I need to change so the result will actually be updated in the observable that was returned by the original request?

Or do I just not understand the intended mechanisms?

2
You're writing an Angular application but you've posted documentation for the React Apollo client? - tombraider
Now that you mention it... :( - Woozar

2 Answers

1
votes

A bit of a wild guess here, but I'm going to suggest this is due to the fact that you're not writing inline Queries; the documentation is going to differ somewhat. Take a look at the refetchQueries prop that you can pass to your Mutation, i.e.

  public upvote() {
    return this.apollo.mutate({
      mutation: gql`mutation upvote($id: String!) {
        upvotePost(id: $id) {
          id
          score
        }
      }`,
      variables: { id: '123' },
      refetchQueries: [],
    });

When your mutation executes, you're telling GraphQL that you want to execute the queries that you provide in that refetchQueries array. As a result of this, the cache will update. However, I'm not 100% convinced that your query will execute because you're not technically subscribed to it, all you've done is execute a one-time promise to fetch the data from the GraphQL endpoint.

1
votes

Now that I used the angular part of the docu instead of the React part, I found the solution. (@tombraider Thank you for pushing me in the right direction.)

Instead of query, I need to use watchQuery.

  public getPost(id: string) {
    return this.apollo.watchQuery({
      query: gql`query getPost($id: String!) {
        post(id: $id) {
          id
          score
        }
      }`,
      variables: { id }
    }).valueChanges;
  }

This changed version of the service-function keeps updateing the GUI.