Case 1: Handle entities without 'id' field
query
const GET_BOOKS = gql`
query {
books {
name
genre
}
}
`;
Entity name: 'books'
An object has multiple keys, for instance, {__typename:'Book", name:'Harry Portal", genre:"Fiction"} ,
update an object in local cache with keys instead of 'id' field
// Update a record without 'id' field in local cache
// for instance, the entity is "books", and the record is below:
// __typename: "Book"
// name: "grapes 🍇 delicious"
// genre: "Fiction"
// updateCachedRecordWithoutId('books',{name:'oldname'},{name:'newname',age:12})
updateCachedRecordWithoutId>(
cacheEntity: string,
filter: T,
data: T
): void {
this.apollo.client.cache.modify({
id: 'ROOT_QUERY',
fields: {
[cacheEntity]: (items = []) => {
const oldItems = cloneDeep(items);
const index = oldItems.findIndex((rec: T) =>
Object.keys(filter).every((key) => {
const k = key as keyof T;
return rec[k] === filter[k];
})
);
if (index < 0) return items;
const newItems = cloneDeep(items);
newItems[index] = { ...newItems[index], ...data };
return newItems;
},
},
});
}
Remove an object from an entity with keys instead of 'id' field
/**
* Remove a record without 'id' field from an entity in apollo cache
* This method is used when you need to remove the cache with a custom key.
*
* @param cacheEntity The name of the entity in the cache.
* @param filter The key or keys of the entity you want to update.
* @example
* removeCachedRecordWithoudId('workorderliness', { workOrderNo:'abcd',lineNo:10000});
* */
removeCachedRecordWithoudId(
cacheEntity: string,
filter: Partial extends object ? Partial : never
): void {
this.apollo.client.cache.modify({
id: 'ROOT_QUERY',
fields: {
[cacheEntity]: (items = [], { DELETE }) => {
const oldItems = cloneDeep(items);
const newItems = oldItems.filter(
(rec: T) =>
!Object.keys(filter).every((key) => {
const k = key as keyof T;
return rec[k] === filter[k];
})
);
// If the record is empty, delete it.
// This is to prevent the cache from returning an empty array. Which causes an error when adding a f
if (newItems.length === 0) return DELETE;
return newItems;
},
},
});
}
Case 2:Handle entities with 'id' field
query
const GET_BOOKS = gql`
query {
books {
id
name
genre
}
}
`;
Entity name: 'books'
In Apollo cache, An object has only one key, for instance, {__ref:'Book:640555"} ,
/**
* Update a single record using id in apollo cache.
*
* @param objectName The name of the object in the cache, which is capitalized, such as 'Book'. However, the
* @param id The id of the object, which is unique for the entity, refering to the record in local cache, s
* @param data The data to update the entity with.
* @example
* updateCachedRecordById('Book', '1233', {age: 12, name: 'New Name' });
*
*/
updateCachedRecordById>(
objectName: string,
id: string,
data: T
): void {
const fields = Object.keys(data)
.map((field) => `${field}`)
.join('\n');
// MyObject is a random fragment name, which can be any name,but should be constant instead of a variable
const fragmentQuery = gql`
fragment MyObject on ${objectName} {
${fields}
}
`;
this.apollo.client.writeFragment({
id: objectName + ':' + id,
fragment: fragmentQuery,
data: data,
});
}
/**
* Remove a record using id from an entity in Apollo cache .
* This method is limited to entities with an 'id' field.
*
* @param cacheEntity The name of the entity in the cache.
* @param id The id of the entity.
* @example
* removeCachedRecordByid('equipments', '1233');
*
*/
removeCachedRecordByid(cacheEntity: string, id: string): void {
this.apollo.client.cache.modify({
id: 'ROOT_QUERY',
fields: {
[cacheEntity]: (items: { __ref: string }[] = [], { readField }) => {
const i = items.findIndex(
(rec: { __ref: string }) => readField('id', rec) === id
);
if (i < 0) return items;
const newRecords = cloneDeep(items);
newRecords.splice(i, 1);
return newRecords;
},
},
});
}