I have the following button in a flatlist that triggers a graphql mutation and after the mutation I do a writeQuery to update the local cache (store). In the update functionf of the mutation I am updating two fields within the cache. essentially when the user touches the like button I chang the boolean value of the like to true and update the like count for that post by +1 (similiar to twitter). However the components in the flatlist do not get updated. I even printed out the apollo store/cache and I see the values getting updated. why is the flatlist not re-rendering after the cache write?
render() {
const { posts, isFetching, lastUpdated, location, navigation, data, likeMutation, username, distancePointLatitude, distancePointLongitude, searchPointLatitude, searchPointLongitude } = this.props
<FlatList
data={data.near}
style={styles.scrollViewContent}
extraData={this.props.store}
//renderSeparator={(sectionId, rowId) => <View key={rowId} style={styles.separator} />}
showsVerticalScrollIndicator={false}
onRefresh={this._onRefresh.bind(this)}
refreshing={this.state.refreshing}
keyExtractor={this._keyExtractor}
renderItem={({item, index}) => item.posts.length != 0 && <ListItem>
{item.posts[0].userInteraction.userLike ? <Icon name='md-heart' style={{ color: 'crimson',fontSize: 28}} />
: <Icon name='heart' style={{ fontSize: 26}}
onPress={() => likeMutation({ variables: { elementId: item.posts[0].postId, userId: username },
update: (store, { data: { addLike } }) => {
// Read the data from our cache for this query.
var thisLocationRadius = {searchPointLongitude: searchPointLongitude,
searchPointLatitude: searchPointLatitude,
radius: fiftyMilesInMeters, distancePointLongitude: distancePointLongitude,
distancePointLatitude: distancePointLatitude };
var data = store.readQuery({ query: getLocalPosts,
variables: {
locationRadius: thisLocationRadius,
userId: username
}, });
data.near[index].posts[0].userInteraction.userLike = true
data.near[index].posts[0].interactionStats.totalLikes + 1
// Write our data back to the cache.
store.writeQuery({ query: getLocalPosts, data });
},
}).catch((error) => {
console.log('there was an error sending the query', error);
})} /> }
}
const HomeWithData = graphql(getLocalPosts, {
options: ({ searchPointLongitude, searchPointLatitude, distancePointLongitude, distancePointLatitude, username }) => ({ variables: { locationRadius: {searchPointLongitude: searchPointLongitude,
searchPointLatitude: searchPointLatitude,
radius: fiftyMilesInMeters, distancePointLongitude: distancePointLongitude,
distancePointLatitude: distancePointLatitude }, userId: username } }),
});
export default compose( connect(mapStateToProps),
HomeWithData,
graphql(like, { name: 'likeMutation' }))(Home);
getLocalPosts Query:
export const getLocalPosts = gql`query getLocalPosts($locationRadius: locationRadius!, , $userId: String!) {
near(locationRadius: $locationRadius){
name,
address,
phonenumber,
email,
website,
about,
location {
longitude,
latitude
},
distance(unit: MILE),
businessId,
hours {
weekDay,
startTime,
endTime
},
posts(isActive: true) {
postText,
postId,
userInteraction(userId: $userId){
userLike
},
interactionStats{
totalLikes
}
},
}
}`;
The mutation field returns an object type that allows you to query for nested fields. This can be useful for fetching an object's new state after an add/update, or to get the old state of an object before a delete. The following mutations would be generated from the above schema.
About GraphQL mutations While we use queries to fetch data, we use mutations to modify server-side data. If queries are the GraphQL equivalent to GET calls in REST, then mutations represent the state-changing methods in REST (like DELETE , PUT , PATCH , etc).
gql. The gql template literal tag can be used to concisely write a GraphQL query that is parsed into a standard GraphQL AST. It is the recommended method for passing queries to Apollo Client. While it is primarily built for Apollo Client, it generates a generic GraphQL AST which can be used by any GraphQL client.
A key argument is an argument for a GraphQL field that's included in cache storage keys for that field. By default, all GraphQL arguments are key arguments, as shown in our feed example: JavaScript.
I think that Apollo takes into account a few things when it decides which query listener should be triggered after a change, including the variables
field.
In your case, your component with the flat list is not re-rendered because the query isn't notified of a change. It isn't notified of a change because Apollo thinks it is a different query than the one you are updating in the store when you call writeQuery
.
So the solution is to add the variables
field when you call writeQuery
. And it should have the same values you use when the query is called.
Assuming these have the correct values, your call to store.writeQuery
should look something like this:
store.writeQuery({
query: getLocalPosts,
data,
variables: {
locationRadius: thisLocationRadius,
userId: username
}
});
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