Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo graphql: writeQuery after mutation does not trigger re-render of flatlist

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
        }
      },
    }
    }`;
like image 915
john Avatar asked Mar 05 '18 02:03

john


People also ask

What does GraphQL mutation return?

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.

What is Gql mutation?

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).

What is Gql in Apollo?

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.

What are key args in Apollo GraphQL for?

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.


1 Answers

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
            }
          });
like image 69
Tal Z Avatar answered Oct 13 '22 05:10

Tal Z