Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo GraphQL client: how to distinguish an optimistic response from a real response into a watchQuery

The question is about the interaction of a mutation, optimistic response, and a watchQuery.

I have a mutation "myMutation" which has an "optimisticResponse" and an implemented "update" function.

Every time I do a mutation query the "update" function is called twice, the first time with optimistic response data and the second one with real data. All is Ok and all as described in the documentation.

Into my "update" function I modify "myQuery" cache data through using readQuery/writeQuery methods.

Every time I modify "myQuery" cache data a watchQuery (based on "myQuery") subscription is called. All is Ok and all as described in the documentation.

But the problem is that I cannot distinguish into my watchQuery whether I receive optimistic response data or real response data. It is crucial for me because the reaction must be different since valuable part of data can be provided by a server only. I should show a GUI element with a special style when I receive an optimistic response and I should prohibit any interactions with it until I receive a real response.

Unfortunately, I can't solve this matter. At a glance, there is no difference between optimistic and real responses. I've googled a lot and haven't found a solution. The only idea I have is adding a special field to my GraphQL data which will show whether a response is received from a server or not. But it looks ugly and smells bad. I am sure, there must be a simple correct way to overcome the problem.

like image 887
Dolios Avatar asked May 16 '18 07:05

Dolios


People also ask

What is optimistic response in Apollo?

Basic optimistic UI Let's say we have an "edit comment" mutation, and we want the UI to update immediately when the user submits the mutation, instead of waiting for the server response. This is what the optimisticResponse parameter to the mutate function provides.

What is difference between useQuery and useLazyQuery?

Unlike with useQuery , when you call useLazyQuery , it does not immediately execute its associated query. Instead, it returns a query function in its result tuple that you call whenever you're ready to execute the query.

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. Cache. 1.


1 Answers

Maybe there is an easier way or there will be one in the future but here is what I know.

The data in optimisticResponse is only provided during the first call to update. That is where you can flag to your update function that it is dealing with optimistic data. You can put any data you want there. I put isOptimistic: true,.

To deal with the watchQuery issue, I recommend you make use of apollo-link-state to add a client-only field or fields to the areas of your data model where optimistic upserts should be known to the display. Don't include isOptimistic in your mutation query so you know it's from the server and not the optimistic response and force it to false if it's not true. See this example:

const SUBMIT_COMMENT_MUTATION = gql`
  mutation submitComment($repoFullName: String!, $commentContent: String!) {
    submitComment(repoFullName: $repoFullName, commentContent: $commentContent) {
      postedBy {
        login
        html_url
      }
      createdAt
      content
    }
  }
`;

const CommentsPageWithMutations = ({ currentUser }) => (
  <Mutation mutation={SUBMIT_COMMENT_MUTATION}>
    {(mutate) => (
      <CommentsPage
        submit={(repoFullName, commentContent) =>
          mutate({
            variables: { repoFullName, commentContent },
            optimisticResponse: {
              __typename: 'Mutation',
              submitComment: {
                __typename: 'Comment',
                postedBy: currentUser,
                createdAt: new Date(),
                content: commentContent,
                isOptimistic: true, // Only provided to update on the optimistic call
              },
            },
            update: (proxy, { data: { submitComment } }) => {
              // Make sure CommentAppQuery includes isOptimistic for each comment added by apollo-link-state
              // submitComment.isOptimistic will be undefined here if it's from the server
              const newComment = {
                ...submitComment,
                isOptimistic: submitCommit.isOptimistic ? true : false,
              };

              // Read the data from our cache for this query.
              const data = proxy.readQuery({ query: CommentAppQuery });

              // Add our comment from the mutation to the end.
              data.comments.push(newComment);

              // Write our data back to the cache.
              proxy.writeQuery({ query: CommentAppQuery, data });
            },
          })
        }
      />
    )}
  </Mutation>
);

See https://www.apollographql.com/docs/link/links/state.html.

like image 137
Casey Benko Avatar answered Nov 29 '22 15:11

Casey Benko