recently started playing around with graphQL and Apollo - apollo-client.
I built a web service on top of graphQL and it's working just fine. The only issue I'm facing is on the client side of the project. For example (please refer to code below), after running createVideo() the data
property of my component which is an observable which is watching the query doesn't refresh automatically and calling apollo.query manually on the callback doesn't seem to take any effect because the query returns the cached results, not the ones from the server.
Am I missing something?
app.component.ts
import {Component, OnInit} from '@angular/core';
import {Apollo, ApolloQueryObservable} from 'apollo-angular';
import 'rxjs/Rx';
import gql from 'graphql-tag';
// http://dev.apollodata.com/angular2/mutations.html
const NewVideoQuery = gql`
mutation AddVideoQuery($title: String!,$duration: Int!, $watched: Boolean!){
createVideo(video: { title: $title, duration: $duration, watched: $watched } ){
id,
title
}
}
`;
const VideoQuery = gql`
{
videos {
id,
title
}
}
`;
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
data: ApolloQueryObservable<any>;
video: any = {};
constructor(private apollo: Apollo) {
}
ngOnInit() {
this.data = this.apollo.watchQuery({query: VideoQuery});
}
createVideo() {
/**
* This will send a mutate query to the server.
*/
// @todo After running the mutate, the watch query doesn't refresh
this.apollo.mutate({
mutation: NewVideoQuery,
variables: {
'title': this.video.title || 'Some Video' + Math.floor(Math.random() * 10),
'duration': 123213,
'watched': true
}
}).subscribe((afterMutation) => {
console.log(afterMutation);
// This fires but query doesn't hit the server since it's coming from cache.
// @todo Not even by re-running it here
this.apollo.query({query: VideoQuery})
.subscribe((data) => {
console.log(data);
});
}, (err) => alert(err));
}
}
//app.component.html
<div *ngFor="let x of data | async | select: 'videos'">
<div><b>{{x.id}}</b>{{x.title}}</div>
</div>
<label>
Title
<input type="text" [(ngModel)]="video.title">
</label>
<button (click)="createVideo()">{{title}}</button>
We create the httpLink that will connect our ApolloClient instance with the GraphQL API. The GraphQL server will be running on http://localhost:4000 . We instantiate ApolloClient by passing in the httpLink and a new instance of an InMemoryCache . Finally, we render the root component of our React app.
In GraphQL, you insert, update or delete data with mutations. A Mutation is a GraphQL Operation that allows you to insert new data or modify the existing data on the server-side. You can think of GraphQL Mutations as the equivalent of POST , PUT , PATCH and DELETE requests in REST.
Updating a single existing entity If a mutation updates a single existing entity, Apollo Client can automatically update that entity's value in its cache when the mutation returns. To do so, the mutation must return the id of the modified entity, along with the values of the fields that were modified.
Update mutations take filter as an input to select specific objects. You can specify set and remove operations on fields belonging to the filtered objects. It returns the state of the objects after updating. Note Executing an empty remove {} or an empty set{} doesn't have any effect on the update mutation.
I figured it out. Apollo-client by default caches our queries and re-runing the same query will of course return the results from cache not from the server.
Naturally, because I did a mutation to create a new record I would expect the server to refresh the dataset automatically which was not the case.
To solve this issue I came up with the idea of re-running my query from the success callback of our createVideo mutation but this time I add a special option called fetchPolicy which supports the following values:
'cache-first' | 'cache-and-network' | 'network-only' | 'cache-only' | 'standby'
Finally my fetch query looks like this:
this.apollo.query({query: VideoQuery, fetchPolicy: 'network-only'})
.subscribe(()=>{ console.log('refresh done, our watchQuery will update') })
Bonus tip:
Another intersting feature about Apollo is that you can set a pooling interval just like this so your data is always in sync with the server
this.data = this.apollo.watchQuery({query: VideoQuery, pollInterval: 10000});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With