You may have seen a lot of console error messages such as:
WARNING: heuristic fragment matching going on!
Missing field temperature in {
"id": "1",
"name": "Hall Light",
"brightnessLevel": 100,
"manufacturer": "Philips",
...
Apollo Client tries to store correct object data in its cache. In other words, each cached object contains fields which match the schema.
But by default, Apollo Client doesn't have access to the schema! This is so it can work easily out of the box.
For most cases, this lack of checking against the schema works fine. Apollo Client just places the returned data into the cache against the object's type and id.
But when you use fragments on interfaces (or unions), that throws a spanner into the works. Apollo Client can make a guess as to which fields belong to which type using its Heuristic Fragment Matcher, but it's not perfect.
Think about a query like this:
{
accessories(offset: 0, limit: 5) {
id
name
... on Light {
brightnessLevel
manufacturer
}
... on Thermostat {
temperature
}
}
}
How will Apollo Client know whether the Accessory retrieved should contain all the fields across all the fragments, or just some of them?
In other words, regardless of the fragment names (which have meaning only to humans), how does it know the relationships between these types? A Thermostat could be a Light could be an Accessory, for all it knows, in which case it would need every field in every fragment.
A solution to this is to give Apollo Client the schema it needs.
-
Create a file in the top level of your homehub client project, calling it
getFragmentSchema.js
. Place the code from here into it. -
Install
node-fetch
:$ npm install node-fetch --save-dev
-
Run this code:
$ node getFragmentSchema.js
It should retrieve the types and their relationships from your server into a JSON file and place it into
src/fragmentTypes.json
. -
Modify
src/index.js
, inserting this code:import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'; import introspectionQueryResultData from './fragmentTypes.json'; const fragmentMatcher = new IntrospectionFragmentMatcher({ introspectionQueryResultData });
-
Modify the
cache
line where you instantiate a new ApolloClient, inserting{ fragmentMatcher }
as follows:cache: new InMemoryCache({ fragmentMatcher })
-
Run your app and check that the errors have gone.
- See Fragment matcher