Defining type policies during runtime in Apollo
Apollo InMemoryCache type policies are used to define field policies for local state, to customize identifier generation by type or to define a custom merge function for the cache.
The standard way of doing this is by defining the type policies during initialization of apollo client like this:
const apolloClient = new ApolloClient({
...
cache: new InMemoryCache({
typePolicies: {
// defining field policy for local state
Article: {
// Field policy map for the Article type
fields: {
// Field policy for the isBookmarked field
isBookmarked: {
// The read function for the isBookmarked field
read(_, { variables }) {
return localStorage
.getItem('BOOKMARKS')
.includes(
variables.articleId
);
}
}
}
},
// customizing identifier generation
Book: {
keyFields: ["isbn"],
}
// defining custom merge function
SearchResults: {
fields: {
results: {
merge(existing = [], incoming: any[]) {
return [...existing, ...incoming];
},
}
}
}
},
});
})
This might not always be possible. You might want to do this at runtime instead. Some of these scenarios:
- If you are loading different chunks at runtime based on user interaction
- You have a microfrontends architecture (like in our case).
To do this you can follow these steps:
1. Get an instance of the cache
const { loading, error, data, client } = useQuery(QUERY);
const cache = client.cache
2. Add policies to the cache
To specify key fields for custom identifier generation
cache.policies.addTypePolicies({
// customizing identifier generation
Book: {
keyFields: ["isbn"],
}
})
Or to define field policy for local storage
cache.policies.addTypePolicies({
Article: {
fields: {
isBookmarked: {
read(_, { variables }) {
return localStorage
.getItem('BOOKMARKS')
.includes(
variables.articleId
);
}
}
}
},
})
Caveat
The reason why it is recommended to configure these at build time is because that way apollo can ensure that the data is not accessed before the type policies are defined.
If you want to do this at runtime, you need to make sure that you call addTypePolicies
before you call useQuery
with the query that uses the type whose policy you are modifying